mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-22 06:12:32 -06:00
Android Builder was modernized to the latest Google stacks. It is compatible with latest build tools version (33) and android (13). The following PR covers: - Migration from deprecated DX to D8 - Migrate from deprecated jarsigner to apksigner - Android Builder works now for both POSIX and Windows - There is no possibility to lunch SDK and AVD managers, the tools that we spawned previously are deprecated. We will need to write our own wrappers for console tools if we want to support that. - Android Builder now parsers AndroidManifest.xml file and informs Android NDK project about minAndroidSdk version from this file. This helps to avoid warnings in the build process.
631 lines
19 KiB
C++
631 lines
19 KiB
C++
#include "Builders.h"
|
|
#include "AndroidBuilder.h"
|
|
|
|
#include <plugin/bz2/bz2.h>
|
|
|
|
#define METHOD_NAME "MakeBuild::" << UPP_FUNCTION_NAME << "(): "
|
|
|
|
#define LDUMP(x) // DUMP(x)
|
|
|
|
MakeBuild::MakeBuild()
|
|
{
|
|
targetmode = 0;
|
|
stoponerrors = true;
|
|
use_target = false;
|
|
}
|
|
|
|
const TargetMode& MakeBuild::GetTargetMode()
|
|
{
|
|
return (targetmode == 0 ? debug : release);
|
|
}
|
|
|
|
Index<String> MakeBuild::PackageConfig(const Workspace& wspc, int package,
|
|
const VectorMap<String, String>& bm, String mainparam,
|
|
Host& host, Builder& b, String *target)
|
|
{
|
|
String packagepath = PackagePath(wspc[package]);
|
|
const Package& pkg = wspc.package[package];
|
|
cfg.Clear();
|
|
MergeWith(mainparam, " ", bm.Get(targetmode ? "RELEASE_FLAGS" : "DEBUG_FLAGS", String()),
|
|
bm.Get("COMMON_FLAGS", String()));
|
|
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");
|
|
}
|
|
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) && bm.Get("DISABLE_BLITZ", "") != "1")
|
|
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 && bm.Get("DISABLE_BLITZ", "") != "1")
|
|
cfg.FindAdd("BLITZ");
|
|
}
|
|
b.AddFlags(cfg);
|
|
host.AddFlags(cfg);
|
|
for(int i = 0; i < pkg.flag.GetCount(); i++) {
|
|
if(MatchWhen(pkg.flag[i].when, cfg.GetKeys())) {
|
|
Vector<String> h = Split(pkg.flag[i].text, ' ');
|
|
for(int i = 0; i < h.GetCount(); i++)
|
|
if(*h[i] == '-')
|
|
cfg.RemoveKey(h[i].Mid(1));
|
|
else
|
|
cfg.FindAdd(h[i]);
|
|
}
|
|
}
|
|
for(int i = 0; i < wspc.GetCount(); i++) {
|
|
const Package& pk = wspc.package[i];
|
|
for(int j = 0; j < pk.GetCount(); j++)
|
|
if(pk[j] == "main.conf")
|
|
cfg.FindAdd(Filter(wspc.package.GetKey(i), [](int c) { return iscid(c) ? c : '_'; }) + "_conf");
|
|
}
|
|
Index<String> h;
|
|
h = clone(cfg); // Retain deep copy (h will be picked)
|
|
return h;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void MakeBuild::CreateHost(Host& host, const String& method, bool darkmode, bool disable_uhd)
|
|
{
|
|
VectorMap<String, String> bm = GetMethodVars(method);
|
|
{
|
|
VectorMap<String, String> env = clone(Environment());
|
|
host.exedirs = SplitDirs(bm.Get("PATH", "") + ';' + env.Get("PATH", ""));
|
|
#ifdef PLATFORM_WIN32
|
|
String p = GetExeDirFile("bin/mingit/cmd");
|
|
if(FileExists(p + "/git.exe"))
|
|
host.exedirs.Add(p);
|
|
env.GetAdd("PATH") = Join(host.exedirs, ";");
|
|
#else
|
|
env.GetAdd("PATH") = Join(host.exedirs, ":");
|
|
#endif
|
|
env.GetAdd("UPP_MAIN__") = GetFileDirectory(PackagePath(GetMain()));
|
|
env.GetAdd("UPP_ASSEMBLY__") = GetVar("UPP");
|
|
if(disable_uhd)
|
|
env.GetAdd("UPP_DISABLE_UHD__") = "1";
|
|
if(darkmode)
|
|
env.GetAdd("UPP_DARKMODE__") = "1";
|
|
// setup LD_LIBRARY_PATH on target dir, needed for all shared builds on posix
|
|
#ifdef PLATFORM_POSIX
|
|
if(target != "")
|
|
{
|
|
String ldPath = GetFileFolder(target) + ";" + env.Get("LD_LIBRARY_PATH", "");
|
|
env.GetAdd("LD_LIBRARY_PATH") = ldPath;
|
|
}
|
|
#endif
|
|
#ifdef PLATFORM_COCOA
|
|
host.exedirs.Append(SplitDirs("/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin")); // sometimes some of these are missing..
|
|
#endif
|
|
|
|
if (IsAndroidMethod(method)) {
|
|
auto jdkPath = bm.Get("JDK_PATH", "");
|
|
if (!jdkPath.IsEmpty()) {
|
|
Cout() << "JDK Path: " << jdkPath << "\n";
|
|
env.GetAdd("JAVA_HOME") = jdkPath;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
void MakeBuild::CreateHost(Host& host, bool darkmode, bool disable_uhd)
|
|
{
|
|
SetupDefaultMethod();
|
|
CreateHost(host, method, darkmode, disable_uhd);
|
|
}
|
|
|
|
One<Builder> MakeBuild::CreateBuilder(Host *host)
|
|
{
|
|
SetupDefaultMethod();
|
|
VectorMap<String, String> bm = GetMethodVars(method);
|
|
String builder = bm.Get("BUILDER", "GCC");
|
|
int q = BuilderMap().Find(builder);
|
|
if(q < 0) {
|
|
PutConsole("Invalid builder " + builder);
|
|
ConsoleShow();
|
|
return nullptr;
|
|
}
|
|
Builder* b = (*BuilderMap().Get(builder))();
|
|
b->host = host;
|
|
b->script = bm.Get("SCRIPT", "");
|
|
if(AndroidBuilder::GetBuildersNames().Find(builder) > -1) {
|
|
AndroidBuilder* pAb = dynamic_cast<AndroidBuilder*>(b);
|
|
if (!pAb) {
|
|
Loge() << METHOD_NAME << "Converting builder to android builder failed.";
|
|
return nullptr;
|
|
}
|
|
pAb->sdk.SetPath((bm.Get("SDK_PATH", "")));
|
|
pAb->ndk.SetPath((bm.Get("NDK_PATH", "")));
|
|
pAb->SetJdk(One<Jdk>(new Jdk(bm.Get("JDK_PATH", ""), host)));
|
|
|
|
String platformVersion = bm.Get("SDK_PLATFORM_VERSION", "");
|
|
if(!platformVersion.IsEmpty())
|
|
pAb->sdk.SetPlatform(platformVersion);
|
|
else
|
|
pAb->sdk.DeducePlatform();
|
|
String buildToolsRelease = bm.Get("SDK_BUILD_TOOLS_RELEASE", "");
|
|
if(!buildToolsRelease.IsEmpty())
|
|
pAb->sdk.SetBuildToolsRelease(buildToolsRelease);
|
|
else
|
|
pAb->sdk.DeduceBuildToolsRelease();
|
|
|
|
pAb->ndk_blitz = bm.Get("NDK_BLITZ", "") == "1";
|
|
if(bm.Get("NDK_ARCH_ARMEABI_V7A", "") == "1")
|
|
pAb->ndkArchitectures.Add("armeabi-v7a");
|
|
if(bm.Get("NDK_ARCH_ARM64_V8A", "") == "1")
|
|
pAb->ndkArchitectures.Add("arm64-v8a");
|
|
if(bm.Get("NDK_ARCH_X86", "") == "1")
|
|
pAb->ndkArchitectures.Add("x86");
|
|
if(bm.Get("NDK_ARCH_X86_64", "") == "1")
|
|
pAb->ndkArchitectures.Add("x86_64");
|
|
pAb->ndkToolchain = bm.Get("NDK_TOOLCHAIN", "");
|
|
pAb->ndkCppRuntime = bm.Get("NDK_CPP_RUNTIME", "");
|
|
pAb->ndkCppFlags = bm.Get("NDK_COMMON_CPP_OPTIONS", "");
|
|
pAb->ndkCFlags = bm.Get("NDK_COMMON_C_OPTIONS", "");
|
|
|
|
b = pAb;
|
|
}
|
|
else {
|
|
// TODO: cpp builder variables only!!!
|
|
b->compiler = bm.Get("COMPILER", "");
|
|
b->include = SplitDirs(Join(GetUppDirs(), ";") + ';' + bm.Get("INCLUDE", "") + ';' + add_includes);
|
|
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->cpp_options = bm.Get("COMMON_CPP_OPTIONS", "");
|
|
b->c_options = bm.Get("COMMON_C_OPTIONS", "");
|
|
b->debug_options = Join(bm.Get("COMMON_OPTIONS", ""), bm.Get("DEBUG_OPTIONS", ""));
|
|
b->release_options = Join(bm.Get("COMMON_OPTIONS", ""), bm.Get("RELEASE_OPTIONS", ""));
|
|
b->common_link = bm.Get("COMMON_LINK", "");
|
|
b->debug_link = bm.Get("DEBUG_LINK", "");
|
|
b->release_link = bm.Get("RELEASE_LINK", "");
|
|
|
|
b->main_conf = !!main_conf.GetCount();
|
|
b->allow_pch = bm.Get("ALLOW_PRECOMPILED_HEADERS", "") == "1";
|
|
b->start_time = start_time;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
int CharFilterSlash(int c)
|
|
{
|
|
return c == '\\' ? '/' : c;
|
|
}
|
|
|
|
bool output_per_assembly;
|
|
|
|
String MakeBuild::OutDir(const Index<String>& cfg, const String& package, const VectorMap<String, String>& bm,
|
|
bool use_target)
|
|
{
|
|
Index<String> excl;
|
|
excl.Add(bm.Get("BUILDER", "GCC"));
|
|
excl.Add("MSC");
|
|
Host().AddFlags(excl);
|
|
Vector<String> 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(output_per_assembly)
|
|
outdir = AppendFileName(outdir, GetAssemblyId());
|
|
if(!use_target)
|
|
outdir = AppendFileName(outdir, package);
|
|
outdir = AppendFileName(outdir, GetFileTitle(method) + "." + Join(x, "."));
|
|
outdir = Filter(outdir, CharFilterSlash);
|
|
return outdir;
|
|
}
|
|
|
|
void MakeBuild::PkgConfig(const Workspace& wspc, const Index<String>& config, Index<String>& pkg_config)
|
|
{
|
|
for(int i = 0; i < wspc.GetCount(); i++)
|
|
for(String h : Split(Gather(wspc.GetPackage(i).pkg_config, config.GetKeys()), ' '))
|
|
pkg_config.FindAdd(h);
|
|
}
|
|
|
|
bool MakeBuild::BuildPackage(const Workspace& wspc, int pkindex, int pknumber, int pkcount,
|
|
String mainparam, String outfile, Vector<String>& linkfile, Vector<String>& immfile,
|
|
String& linkopt, bool link)
|
|
{
|
|
String package = wspc[pkindex];
|
|
String mainpackage = wspc[0];
|
|
const Package& pkg = wspc.package[pkindex];
|
|
VectorMap<String, String> bm = GetMethodVars(method);
|
|
if(bm.GetCount() == 0) {
|
|
PutConsole(GetInvalidBuildMethodError(method));
|
|
ConsoleShow();
|
|
return false;
|
|
}
|
|
Host host;
|
|
CreateHost(host, false, false);
|
|
host.onefile = onefile;
|
|
One<Builder> b = CreateBuilder(&host);
|
|
if(!b)
|
|
return false;
|
|
b->config = PackageConfig(wspc, pkindex, bm, mainparam, host, *b);
|
|
PkgConfig(wspc, b->config, b->pkg_config);
|
|
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<String> mcfg = PackageConfig(wspc, 0, bm, mainparam, host, *b, &mainfn);
|
|
HdependClearDependencies();
|
|
for(int i = 0; i < pkg.GetCount(); i++) {
|
|
const Array<OptItem>& 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 {
|
|
#ifdef PLATFORM_COCOA
|
|
if(m.target_override && !IsNull(m.target)
|
|
&& IsFolder(m.target) && GetFileExt(m.target) == ".app")
|
|
target = NormalizePath(m.target);
|
|
else
|
|
#endif
|
|
if(m.target_override && !IsNull(m.target) && IsFolder(m.target))
|
|
target = 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 = NormalizePath(AppendFileName(tout, m.target));
|
|
else
|
|
if(IsFullPath(mainfn))
|
|
target = mainfn;
|
|
else
|
|
target = NormalizePath(AppendFileName(tout, mainfn));
|
|
}
|
|
b->target = target;
|
|
b->mainpackage = mainpackage;
|
|
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, immfile, linkopt,
|
|
GetAllUses(wspc, pkindex, bm, mainparam, host, *b),
|
|
GetAllLibraries(wspc, pkindex, bm, mainparam, host, *b),
|
|
targetmode - 1);
|
|
target = b->target; // apple app bundle can change target
|
|
Vector<String> errors = PickErrors();
|
|
for(String p : errors)
|
|
DeleteFile(p);
|
|
if(!ok || !errors.IsEmpty())
|
|
return false;
|
|
if(link) {
|
|
ok = b->Link(linkfile, linkopt, GetTargetMode().createmap);
|
|
PutLinkingEnd(ok);
|
|
errors = PickErrors();
|
|
for(String p : errors)
|
|
DeleteFile(p);
|
|
if(!ok || !errors.IsEmpty())
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MakeBuild::SetHdependDirs()
|
|
{
|
|
Vector<String> include = SplitDirs(GetVar("UPP") + ';'
|
|
+ GetMethodVars(method).Get("INCLUDE", "") + ';'
|
|
+ Environment().Get("INCLUDE", "")
|
|
#ifdef PLATFORM_POSIX
|
|
+ ";/usr/include;/usr/local/include;"
|
|
#endif
|
|
+ add_includes
|
|
);
|
|
// Also adding internal includes
|
|
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++)
|
|
include.Add(SourcePath(wspc[i], pkg.include[j].text));
|
|
}
|
|
|
|
HdependSetDirs(pick(include));
|
|
}
|
|
|
|
Vector<String> MakeBuild::GetAllUses(const Workspace& wspc, int f,
|
|
const VectorMap<String, String>& bm, String mainparam, Host& host, Builder& builder)
|
|
{ // Gathers all uses, including subpackages, to support SO builds
|
|
String package = wspc[f];
|
|
Index<String> all_uses;
|
|
bool warn = true;
|
|
int n = 0;
|
|
while(f >= 0) {
|
|
const Package& p = wspc.package[f];
|
|
Index<String> config = PackageConfig(wspc, f, bm, mainparam, host, builder);
|
|
for(int fu = 0; fu < p.uses.GetCount(); fu++) {
|
|
if(MatchWhen(p.uses[fu].when, config.GetKeys())) {
|
|
if(p.uses[fu].text != package)
|
|
all_uses.FindAdd(p.uses[fu].text);
|
|
else if(warn) {
|
|
PutConsole(Format("%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<String> MakeBuild::GetAllLibraries(const Workspace& wspc, int index,
|
|
const VectorMap<String, String>& bm, String mainparam,
|
|
Host& host, Builder& builder)
|
|
{
|
|
Vector<String> uses = GetAllUses(wspc, index, bm, mainparam, host, builder);
|
|
uses.Add(wspc[index]);
|
|
Index<String> libraries;
|
|
|
|
for(int i = 0; i < uses.GetCount(); i++) {
|
|
int f = wspc.package.Find(UnixPath(uses[i]));
|
|
if(f >= 0) {
|
|
const Package& pk = wspc.package[f];
|
|
Index<String> config = PackageConfig(wspc, f, bm, mainparam, host, builder);
|
|
Vector<String> 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)
|
|
{
|
|
InitBlitz();
|
|
|
|
String hfile = outfile + ".xxx";
|
|
SaveFile(hfile, "");
|
|
start_time = GetFileTime(hfile); // Defensive way to get correct filetime of start
|
|
DeleteFile(hfile);
|
|
|
|
BeginBuilding(clear_console);
|
|
bool ok = true;
|
|
main_conf.Clear();
|
|
add_includes.Clear();
|
|
if(wspc.GetCount()) {
|
|
for(int i = 0; i < wspc.GetCount(); i++) {
|
|
const Package& pk = wspc.package[i];
|
|
for(int j = 0; j < pk.GetCount(); j++)
|
|
if(pk[j] == "main.conf") {
|
|
String pn = wspc[i];
|
|
String p = SourcePath(pn, "main.conf");
|
|
main_conf << "// " << pn << "\r\n" << LoadFile(p) << "\r\n";
|
|
PutConsole("Found " + p);
|
|
}
|
|
}
|
|
|
|
if(main_conf.GetCount()) {
|
|
VectorMap<String, String> bm = GetMethodVars(method);
|
|
Host host;
|
|
CreateHost(host, false, false);
|
|
One<Builder> b = CreateBuilder(&host);
|
|
if(b) {
|
|
Index<String> mcfg = PackageConfig(wspc, 0, bm, mainparam, host, *b, NULL);
|
|
String outdir = OutDir(mcfg, wspc[0], bm, false);
|
|
String path = AppendFileName(outdir, "main.conf.h");
|
|
RealizePath(path);
|
|
SaveChangedFile(path, main_conf);
|
|
PutConsole("Saving " + path);
|
|
PutVerbose(main_conf);
|
|
add_includes << outdir << ';';
|
|
}
|
|
}
|
|
|
|
Vector<int> build_order;
|
|
if(cfg.Find("SO") < 0) {
|
|
for(int i = 1; i < wspc.GetCount(); i++)
|
|
build_order.Add(i);
|
|
}
|
|
else {
|
|
Index<int> 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(UnixPath(pk.uses[u].text))) >= 0) {
|
|
delay = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!delay)
|
|
break;
|
|
}
|
|
if(t >= remaining.GetCount()) // Progress even if circular references present
|
|
t = 0;
|
|
build_order.Add(remaining[t]);
|
|
remaining.Remove(t);
|
|
}
|
|
}
|
|
|
|
String mainpackage = wspc[0];
|
|
Vector<String> linkfile, immfile;
|
|
String linkopt = Merge(" ", GetMethodVars(method).Get("COMMON_LINK", Null),
|
|
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, immfile, 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, immfile, linkopt, ok) && ok;
|
|
}
|
|
}
|
|
EndBuilding(ok);
|
|
SetErrorEditor();
|
|
return ok;
|
|
}
|
|
|
|
void MakeBuild::BuildWorkspace(Workspace& wspc, Host& host, Builder& builder)
|
|
{
|
|
Index<String> p = PackageConfig(GetIdeWorkspace(), 0, GetMethodVars(method), mainconfigparam,
|
|
host, builder);
|
|
wspc.Scan(GetMain(), p.GetKeys());
|
|
}
|
|
|
|
bool MakeBuild::Build()
|
|
{
|
|
if(GetMethodVars(method).GetCount() == 0) {
|
|
PutConsole(GetInvalidBuildMethodError(method));
|
|
ConsoleShow();
|
|
return false;
|
|
}
|
|
Host host;
|
|
CreateHost(host, false, false);
|
|
One<Builder> builder = CreateBuilder(&host);
|
|
if(!builder)
|
|
return false;
|
|
Workspace wspc;
|
|
BuildWorkspace(wspc, host, *builder);
|
|
return Build(wspc, mainconfigparam, Null);
|
|
}
|
|
|
|
void MakeBuild::CleanPackage(const Workspace& wspc, int package)
|
|
{
|
|
PutConsole(Format("Cleaning %s", wspc[package]));
|
|
Host host;
|
|
CreateHost(host, false, false);
|
|
One<Builder> builder = CreateBuilder(&host);
|
|
if(!builder)
|
|
return;
|
|
String outdir = OutDir(PackageConfig(wspc, package, GetMethodVars(method), mainconfigparam,
|
|
host, *builder), wspc[package], GetMethodVars(method));
|
|
// TODO: almost perfect, but target will be detected after build. if build does not occur the target is empty :(
|
|
// How to make sure we know target? Target directory is where android project sandbox is.
|
|
builder->target = target;
|
|
builder->CleanPackage(wspc[package], outdir);
|
|
}
|
|
|
|
void MakeBuild::Clean()
|
|
{
|
|
ConsoleClear();
|
|
|
|
Host host;
|
|
CreateHost(host, false, false);
|
|
One<Builder> builder = CreateBuilder(&host);
|
|
if(!builder)
|
|
return;
|
|
builder->target = target;
|
|
|
|
Workspace wspc;
|
|
BuildWorkspace(wspc, host, *builder);
|
|
for(int i = 0; i < wspc.GetCount(); i++)
|
|
CleanPackage(wspc, i);
|
|
|
|
builder->AfterClean();
|
|
|
|
PutConsole("...done");
|
|
}
|
|
|
|
void MakeBuild::RebuildAll()
|
|
{
|
|
Clean();
|
|
Build();
|
|
}
|
|
|
|
String MakeBuild::GetInvalidBuildMethodError(const String& method)
|
|
{
|
|
return "Invalid build method " + method + " (" + GetMethodPath(method) + ").";
|
|
}
|
|
|
|
bool MakeBuild::IsAndroidMethod(const String& method) const
|
|
{
|
|
VectorMap<String, String> bm = GetMethodVars(method);
|
|
String builder = bm.Get("BUILDER", "");
|
|
if (builder.IsEmpty()) {
|
|
Loge() << METHOD_NAME << "Failed to find builder.";
|
|
return false;
|
|
}
|
|
|
|
auto pBuilder = (*BuilderMap().Get(builder))();
|
|
if (!pBuilder) {
|
|
Loge() << METHOD_NAME << "Failed to get builder from builder map.";
|
|
return false;
|
|
}
|
|
|
|
return AndroidBuilder::GetBuildersNames().Find(builder) > -1;
|
|
}
|