IDE: Android Builder update to 2022 stack (#116)

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.
This commit is contained in:
Zbigniew Rębacz 2022-12-04 18:24:34 +01:00 committed by GitHub
parent 4c6cdaf417
commit a83d877bd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 339 additions and 130 deletions

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.upp.AndroidMath"> package="org.upp.AndroidMath">
<uses-sdk android:minSdkVersion="21" />
<application <application
android:allowBackup="true"> android:allowBackup="true">
<activity android:name=".AndroidMathActivity" <activity android:name=".AndroidMathActivity"

View file

@ -65,32 +65,31 @@ public:
String PlatformToolsDir() const; String PlatformToolsDir() const;
String ToolsDir() const; String ToolsDir() const;
bool HasD8() const;
String AaptPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "aapt" + GetExeExt(); } String AaptPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "aapt" + GetExeExt(); }
String ApksignerPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "apksigner" + Android::GetScriptExt(); }
String DxPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "dx" + Android::GetScriptExt(); } String DxPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "dx" + Android::GetScriptExt(); }
String D8Path() const { return ConcreteBuildToolsDir() + DIR_SEPS + "d8" + Android::GetScriptExt(); }
String ZipalignPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "zipalign" + GetExeExt(); } String ZipalignPath() const { return ConcreteBuildToolsDir() + DIR_SEPS + "zipalign" + GetExeExt(); }
String AndroidJarPath() const { return ConcretePlatformDir() + DIR_SEPS + "android.jar"; } String AndroidJarPath() const { return ConcretePlatformDir() + DIR_SEPS + "android.jar"; }
String AdbPath() const { return PlatformToolsDir() + DIR_SEPS + "adb" + GetExeExt(); } String AdbPath() const { return PlatformToolsDir() + DIR_SEPS + "adb" + GetExeExt(); }
String AndroidPath() const { return ToolsDir() + DIR_SEPS + "android" + Android::GetScriptExt(); } String AndroidPath() const { return ToolsDir() + DIR_SEPS + "android" + Android::GetScriptExt(); }
String EmulatorPath() const { return ToolsDir() + DIR_SEPS + "emulator" + GetExeExt(); } String EmulatorPath() const { return ToolsDir() + DIR_SEPS + "emulator" + GetExeExt(); }
String MonitorPath() const { return ToolsDir() + DIR_SEPS + "monitor" + Android::GetScriptExt(); }
public:
String GetLauchSDKManagerCmd() const { return NormalizeExePath(AndroidPath()) + " sdk"; }
String GetLauchAVDManagerCmd() const { return NormalizeExePath(AndroidPath()) + " avd"; }
public: public:
String GetPath() const { return this->path; } String GetPath() const { return this->path; }
String GetPlatform() const { return this->platform; } String GetPlatform() const { return this->platform; }
String GetBuildToolsRelease() const { return this->buildToolsRelease; } String GetBuildToolsRelease() const { return this->build_tools_release; }
void SetPath(const String& path) { this->path = path; } void SetPath(const String& path) { this->path = path; }
void SetPlatform(const String& platform) { this->platform = platform; } void SetPlatform(const String& platform) { this->platform = platform; }
void SetBuildToolsRelease(const String& buildToolsRelease) { this->buildToolsRelease = buildToolsRelease; } void SetBuildToolsRelease(const String& build_tools_release) { this->build_tools_release = build_tools_release; }
private: private:
String path; String path;
String platform; String platform;
String buildToolsRelease; String build_tools_release;
}; };
class AndroidNDK { class AndroidNDK {
@ -151,11 +150,26 @@ private:
class AndroidManifest { class AndroidManifest {
public: public:
AndroidManifest(); static constexpr const char* FILE_NAME = "AndroidManifest.xml";
class UsesSdk {
public:
int minSdkVersion = Null;
int targetSdkVersion = Null;
int maxSdkVersion = Null;
};
public:
AndroidManifest(const String& path);
virtual ~AndroidManifest(); virtual ~AndroidManifest();
private: bool Parse();
public:
One<UsesSdk> uses_sdk;
private:
String path;
}; };
} }

View file

@ -1,15 +1,49 @@
#include "Android.h" #include "Android.h"
#define METHOD_NAME "AndroidManifest::" << UPP_FUNCTION_NAME << "(): "
namespace Upp { namespace Upp {
AndroidManifest::AndroidManifest() AndroidManifest::AndroidManifest(const String& path)
: path(path)
{ {
} }
AndroidManifest::~AndroidManifest() AndroidManifest::~AndroidManifest()
{ {
}
bool AndroidManifest::Parse()
{
String xml = LoadFile(path);
if (xml.IsVoid()) {
Loge() << METHOD_NAME << "Failed to load manifest file \"" + path + "\".";
return false;
}
try {
XmlParser p(xml);
while(!p.IsTag()) {
p.Skip();
}
p.PassTag("manifest");
while (!p.End()) {
if(p.TagE("uses-sdk")) {
uses_sdk.Create();
uses_sdk->minSdkVersion = p.Int("android:minSdkVersion");
uses_sdk->targetSdkVersion = p.Int("android:targetSdkVersion");
uses_sdk->maxSdkVersion = p.Int("android:maxSdkVersion");
}
p.Skip();
}
} catch(const XmlError& e) {
Loge() << METHOD_NAME << "Failed to parse manifest file with error \"" + e + "\".";
return false;
}
return true;
} }
} }

View file

@ -37,7 +37,7 @@ void AndroidSDK::DeducePlatform()
void AndroidSDK::DeduceBuildToolsRelease() void AndroidSDK::DeduceBuildToolsRelease()
{ {
buildToolsRelease = FindDefaultBuildToolsRelease(); build_tools_release = FindDefaultBuildToolsRelease();
} }
bool AndroidSDK::Validate() const bool AndroidSDK::Validate() const
@ -224,7 +224,7 @@ String AndroidSDK::PlatformsDir() const
String AndroidSDK::ConcreteBuildToolsDir() const String AndroidSDK::ConcreteBuildToolsDir() const
{ {
return BuildToolsDir() + DIR_SEPS + buildToolsRelease; return BuildToolsDir() + DIR_SEPS + build_tools_release;
} }
String AndroidSDK::ConcretePlatformDir() const String AndroidSDK::ConcretePlatformDir() const
@ -244,4 +244,9 @@ String AndroidSDK::ToolsDir() const
// --------------------------------------------------------------- // ---------------------------------------------------------------
bool AndroidSDK::HasD8() const
{
return FileExists(D8Path());
}
} }

View file

@ -20,6 +20,7 @@ public:
String GetResDir() const; String GetResDir() const;
String GetBuildDir() const; String GetBuildDir() const;
String GetClassesDir() const; String GetClassesDir() const;
String GetIntermediatesDir() const;
String GetBinDir() const; String GetBinDir() const;
String GetObjDir() const; String GetObjDir() const;
String GetObjLocalDir() const; String GetObjLocalDir() const;
@ -28,6 +29,8 @@ public:
String GetJniMakeFilePath() const; String GetJniMakeFilePath() const;
String GetJniApplicationMakeFilePath() const; String GetJniApplicationMakeFilePath() const;
Vector<String> GetClassessFiles() const;
bool IsDebug() const; bool IsDebug() const;
bool IsRelease() const; bool IsRelease() const;

View file

@ -63,8 +63,6 @@ bool AndroidBuilder::BuildPackage(
Index<String> noBlitzNativeSourceFiles; Index<String> noBlitzNativeSourceFiles;
String androidManifestPath;
String javaSourcesDir = project->GetJavaDir(); String javaSourcesDir = project->GetJavaDir();
String jniSourcesDir = project->GetJniDir(); String jniSourcesDir = project->GetJniDir();
String pkgJavaSourcesDir = javaSourcesDir + DIR_SEPS + package; String pkgJavaSourcesDir = javaSourcesDir + DIR_SEPS + package;
@ -115,16 +113,21 @@ bool AndroidBuilder::BuildPackage(
} }
else else
if(BuilderUtils::IsXmlFile(filePath)) { if(BuilderUtils::IsXmlFile(filePath)) {
if(isMainPackage && fileName == "AndroidManifest.xml") { if(isMainPackage && fileName == AndroidManifest::FILE_NAME) {
if(androidManifestPath.GetCount()) { if (manifest) {
PutConsole("AndroidManifest.xml is duplicated."); PutConsole("Manifest file already exists. There should be only one AndroidManifest.xml in the project.");
return false; return false;
} }
if(!FileCopy(filePath, project->GetManifestPath())) if(!FileCopy(filePath, project->GetManifestPath())) {
return false; return false;
}
androidManifestPath = filePath; manifest.Create(filePath);
if (!manifest->Parse()) {
PutConsole("Failed to parse AndroidManifest.xml.");
return false;
}
} }
} }
else else
@ -138,8 +141,8 @@ bool AndroidBuilder::BuildPackage(
} }
} }
if(isMainPackage && androidManifestPath.IsEmpty()) { if(isMainPackage && !manifest) {
PutConsole("Failed to find Android manifest file."); PutConsole("Failed to find Android manifest file in. Make sure AndroidManifest.xml is present in main package.");
return false; return false;
} }
@ -196,21 +199,28 @@ bool AndroidBuilder::Link(
bool createmap) bool createmap)
{ {
InitProject(); InitProject();
if(!ValidateBuilderEnviorement()) if(!ValidateBuilderEnviorement()) {
return false; return false;
}
ManageProjectCohesion(); ManageProjectCohesion();
PutConsole("Building Android Project"); PutConsole("Building Android Project");
StringStream ss; if(!manifest) {
if(!GenerateRFile()) PutConsole("Android manifest has not been detected. Make sure your main package contains AndroidManifest.xml.");
return false; return false;
if(!RealizeLinkDirectories()) }
if(!GenerateRFile()) {
return false; return false;
}
if(!RealizeLinkDirectories()) {
return false;
}
// We need to compile java packages in this place, because we need to generate "R.java" file before... // We need to compile java packages in this place, because we need to generate "R.java" file before...
// We don't know which packages contain resources. // We don't know which packages contain resources.
int time; int time;
StringStream ss;
if(linkfile.GetCount()) { if(linkfile.GetCount()) {
PutConsole("-----"); PutConsole("-----");
PutConsole("Compiling java sources..."); PutConsole("Compiling java sources...");
@ -250,18 +260,8 @@ bool AndroidBuilder::Link(
PutConsole("Native sources compiled in " + GetPrintTime(time) + "."); PutConsole("Native sources compiled in " + GetPrintTime(time) + ".");
} }
if(DirectoryExists(project->GetClassesDir())) { if (!GenerateDexFile()) {
PutConsole("-----"); return false;
PutConsole("Creating dex file...");
String dxCmd;
dxCmd << NormalizeExePath(sdk.DxPath());
dxCmd << " --dex ";
dxCmd << "--output=" << project->GetBinDir() << DIR_SEPS << "classes.dex ";
dxCmd << project->GetClassesDir();
if(Execute(dxCmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
} }
PutConsole("Creating apk file..."); PutConsole("Creating apk file...");
@ -284,13 +284,20 @@ bool AndroidBuilder::Link(
if(DirectoryExists(project->GetLibsDir())) { if(DirectoryExists(project->GetLibsDir())) {
PutConsole("Adding native libraries to apk..."); PutConsole("Adding native libraries to apk...");
if(!AddSharedLibsToApk(unsignedApkPath)) if(!AddSharedLibsToApk(unsignedApkPath)) {
return false; return false;
}
} }
// In release mode we definitly shouldn't signing apk!!! String unsignedAlignedApkPath = GetSandboxDir() + DIR_SEPS + GetFileTitle(target) + ".aligned.unsigned.apk";
if(!SignApk(target, unsignedApkPath)) DeleteFile(unsignedAlignedApkPath);
if(!AlignApk(unsignedAlignedApkPath, unsignedApkPath)) {
return false; return false;
}
if(!SignApk(target, unsignedAlignedApkPath)) {
return false;
}
return true; return true;
} }
@ -459,58 +466,53 @@ bool AndroidBuilder::RealizeLinkDirectories() const
return true; return true;
} }
bool AndroidBuilder::SignApk(const String& target, const String& unsignedApkPath) bool AndroidBuilder::AlignApk(const String& target, const String& unsignedApkPath)
{ {
StringStream ss; StringStream ss;
String signedApkPath = GetSandboxDir() + DIR_SEPS + GetFileTitle(target) + ".signed.apk"; PutConsole("Aliging apk file...");
if(HasFlag("DEBUG")) { DeleteFile(target);
String keystorePath = GetSandboxDir() + DIR_SEPS + "debug.keystore"; String zipalignCmd;
if(!GenerateDebugKey(keystorePath)) zipalignCmd << NormalizeExePath(sdk.ZipalignPath()) << " -f 4 ";
return false; zipalignCmd << unsignedApkPath << " " << target;
if(Execute(zipalignCmd, ss) != 0) {
PutConsole("Signing apk file..."); PutConsole(ss.GetResult());
DeleteFile(signedApkPath); return false;
String jarsignerCmd;
jarsignerCmd << NormalizeExePath(jdk->GetJarsignerPath());
// Up to Java 6.0 below alogirms was by default
// (In Java 7.0 and above we need to manually specific this algorithms)
jarsignerCmd << " -sigalg SHA1withRSA";
jarsignerCmd << " -digestalg SHA1";
jarsignerCmd << " -keystore " + keystorePath;
jarsignerCmd << " -storepass android";
jarsignerCmd << " -keypass android";
// TODO: not sure about below line. But I think for debug purpose we shouldn't use tsa.
// http://en.wikipedia.org/wiki/Trusted_timestamping
//jarsignerCmd << " -tsa https://timestamp.geotrust.com/tsa";
jarsignerCmd << " -signedjar " << signedApkPath;
jarsignerCmd << " " << unsignedApkPath;
jarsignerCmd << " androiddebugkey";
//PutConsole(jarsignerCmd);
if(Execute(jarsignerCmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
PutConsole("Aliging apk file...");
DeleteFile(target);
String zipalignCmd;
zipalignCmd << NormalizeExePath(sdk.ZipalignPath());
zipalignCmd << " -f 4 ";
zipalignCmd << (HasFlag("DEBUG") ? signedApkPath : unsignedApkPath) << " ";
zipalignCmd << target;
//PutConsole(zipalignCmd);
if(Execute(zipalignCmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
} }
return true; return true;
} }
bool AndroidBuilder::SignApk(const String& target, const String& unsignedApkPath)
{
if(!HasFlag("DEBUG")) {
return false;
}
StringStream ss;
String signedApkPath = GetSandboxDir() + DIR_SEPS + GetFileTitle(target) + ".signed.apk";
String keystorePath = GetSandboxDir() + DIR_SEPS + "debug.keystore";
if(!GenerateDebugKey(keystorePath)) {
return false;
}
PutConsole("Signing apk file...");
DeleteFile(signedApkPath);
String cmd;
cmd << NormalizeExePath(sdk.ApksignerPath());
cmd << " sign --ks " << keystorePath << " --ks-pass pass:android" << " --out " << signedApkPath << " " << unsignedApkPath;
if(Execute(cmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
CopyFile(target, signedApkPath);
return true;
}
bool AndroidBuilder::GenerateDebugKey(const String& keystorePath) bool AndroidBuilder::GenerateDebugKey(const String& keystorePath)
{ {
StringStream ss; StringStream ss;
@ -536,8 +538,8 @@ bool AndroidBuilder::GenerateDebugKey(const String& keystorePath)
bool AndroidBuilder::AddSharedLibsToApk(const String& apkPath) bool AndroidBuilder::AddSharedLibsToApk(const String& apkPath)
{ {
// TODO: A little bit workearound (I know one thing that shared libs should be in "lib" directory not in "libs") // TODO: Consider using environment variable NDK_LIBS_OUT form NDK r9 instead of
// So, we need to create temporary lib directory with .so files :( // creating temporary lib directory that will be deleted after inserting files to APK.
const String libDir = project->GetDir() + DIR_SEPS + "lib"; const String libDir = project->GetDir() + DIR_SEPS + "lib";
Vector<String> sharedLibsToAdd; Vector<String> sharedLibsToAdd;
@ -563,16 +565,24 @@ bool AndroidBuilder::AddSharedLibsToApk(const String& apkPath)
String aaptAddCmd; String aaptAddCmd;
aaptAddCmd << NormalizeExePath(sdk.AaptPath()); aaptAddCmd << NormalizeExePath(sdk.AaptPath());
aaptAddCmd << " add " << apkPath; aaptAddCmd << " add " << apkPath;
for(int i = 0; i < sharedLibsToAdd.GetCount(); i++) for(int i = 0; i < sharedLibsToAdd.GetCount(); i++) {
aaptAddCmd << " " << sharedLibsToAdd[i]; #ifdef PLATFORM_WIN32
// PutConsole(aaptAddCmd); // NOTE: Without conversion to UNIX directory format libraries will be added at the top
// of APK file and APK will be broken.
sharedLibsToAdd[i].Replace("\\", "/");
#endif
aaptAddCmd << " " << sharedLibsToAdd[i] << "";
}
StringStream ss; StringStream ss;
if(Execute(aaptAddCmd, ss) != 0) { if(Execute(aaptAddCmd, ss) != 0) {
PutConsole(ss.GetResult()); PutConsole(ss.GetResult());
return false; return false;
} }
if(!DeleteFolderDeep(libDir))
if(!DeleteFolderDeep(libDir)) {
return false; return false;
}
return true; return true;
} }
@ -619,8 +629,13 @@ void AndroidBuilder::UpdateFile(const String& path, const String& data)
void AndroidBuilder::GenerateApplicationMakeFile() void AndroidBuilder::GenerateApplicationMakeFile()
{ {
String platform;
AndroidApplicationMakeFile makeFile; AndroidApplicationMakeFile makeFile;
makeFile.SetPlatform(sdk.GetPlatform()); if (manifest && manifest->uses_sdk && !IsNull(manifest->uses_sdk->minSdkVersion)) {
String platform = "android-" + IntStr(manifest->uses_sdk->minSdkVersion);
makeFile.SetPlatform(platform);
}
makeFile.SetArchitectures(ndkArchitectures); makeFile.SetArchitectures(ndkArchitectures);
makeFile.SetCppRuntime(ndkCppRuntime); makeFile.SetCppRuntime(ndkCppRuntime);
makeFile.SetCppFlags(ndkCppFlags); makeFile.SetCppFlags(ndkCppFlags);
@ -633,6 +648,7 @@ void AndroidBuilder::GenerateApplicationMakeFile()
PutVerbose("CppFlags: " + ndkCppFlags); PutVerbose("CppFlags: " + ndkCppFlags);
PutVerbose("CFlags: " + ndkCFlags); PutVerbose("CFlags: " + ndkCFlags);
PutVerbose("Toolchain: " + ndkToolchain); PutVerbose("Toolchain: " + ndkToolchain);
PutVerbose("Platform: " + platform);
UpdateFile(project->GetJniApplicationMakeFilePath(), makeFile.ToString()); UpdateFile(project->GetJniApplicationMakeFilePath(), makeFile.ToString());
} }
@ -700,6 +716,79 @@ bool AndroidBuilder::GenerateRFile()
return true; return true;
} }
bool AndroidBuilder::GenerateDexFile()
{
if(!DirectoryExists(project->GetClassesDir())) {
return true;
}
PutConsole("-----");
if (sdk.HasD8()) {
return GenerateDexFileUsingD8();
}
return GenerateDexFileUsingDx();
}
bool AndroidBuilder::GenerateDexFileUsingD8()
{
PutConsole("Creating dex file using d8...");
String cmd;
StringStream ss;
const auto outputFile = project->GetIntermediatesDir() << DIR_SEPS << "classes.jar";
cmd << NormalizeExePath(sdk.D8Path());
cmd << " --output " << outputFile << " ";
auto classesFiles = project->GetClassessFiles();
for (const auto& file : classesFiles) {
cmd << file << " ";
}
if(Execute(cmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
cmd.Clear();
{
// TODO: Replace with ScopeExit once it will be present in upp core..
String currentDir = GetCurrentDirectory();
ChangeCurrentDirectory(project->GetBinDir());
cmd << NormalizeExePath(jdk->GetJarPath()) << " xf " << outputFile;
if(Execute(cmd, ss) != 0) {
ChangeCurrentDirectory(currentDir);
PutConsole(ss.GetResult());
return false;
}
ChangeCurrentDirectory(currentDir);
}
return true;
}
bool AndroidBuilder::GenerateDexFileUsingDx()
{
PutConsole("Creating dex file using dx...");
String cmd;
StringStream ss;
cmd << NormalizeExePath(sdk.DxPath());
cmd << " --dex ";
cmd << "--output=" << project->GetBinDir() << DIR_SEPS << "classes.dex ";
cmd << project->GetClassesDir();
if(Execute(cmd, ss) != 0) {
PutConsole(ss.GetResult());
return false;
}
return true;
}
bool AndroidBuilder::PreprocessJava(const String& package, const String& file, const String& target) bool AndroidBuilder::PreprocessJava(const String& package, const String& file, const String& target)
{ {
StringStream ss; StringStream ss;

View file

@ -68,11 +68,15 @@ protected:
void GenerateApplicationMakeFile(); void GenerateApplicationMakeFile();
void GenerateMakeFile(); void GenerateMakeFile();
bool GenerateRFile(); bool GenerateRFile();
bool GenerateDexFile();
bool GenerateDexFileUsingD8();
bool GenerateDexFileUsingDx();
protected: protected:
bool ValidateBuilderEnviorement(); bool ValidateBuilderEnviorement();
void PutErrorOnConsole(const String& msg); void PutErrorOnConsole(const String& msg);
bool AlignApk(const String& target, const String& unsignedApkPath);
bool SignApk(const String& target, const String& unsignedApkPath); bool SignApk(const String& target, const String& unsignedApkPath);
bool GenerateDebugKey(const String& keystorePath); bool GenerateDebugKey(const String& keystorePath);
@ -99,6 +103,7 @@ private:
One<Jdk> jdk; One<Jdk> jdk;
One<AndroidProject> project; One<AndroidProject> project;
One<AndroidBuilderCommands> commands; One<AndroidBuilderCommands> commands;
One<AndroidManifest> manifest;
const Workspace& wspc; const Workspace& wspc;

View file

@ -50,7 +50,12 @@ String AndroidProject::GetBuildDir() const
String AndroidProject::GetClassesDir() const String AndroidProject::GetClassesDir() const
{ {
return this->dir + DIR_SEPS + "classes"; return GetIntermediatesDir() + DIR_SEPS + "classes";
}
String AndroidProject::GetIntermediatesDir() const
{
return this->dir + DIR_SEPS + "intermediates";
} }
String AndroidProject::GetBinDir() const String AndroidProject::GetBinDir() const
@ -87,6 +92,37 @@ String AndroidProject::GetJniApplicationMakeFilePath() const
// ------------------------------------------------------------------- // -------------------------------------------------------------------
Vector<String> AndroidProject::GetClassessFiles() const
{
BiVector<String> dirs = { GetClassesDir() };
Vector<String> classesFiles;
while(!dirs.IsEmpty())
{
for(FindFile ff(AppendFileName(dirs.Head(), "*")); ff; ff.Next()) {
if (ff.IsHidden() || ff.IsSymLink()) {
continue;
}
auto path = ff.GetPath();
if (ff.IsFolder()) {
dirs.AddTail(path);
continue;
}
if (path.EndsWith(".class")) {
classesFiles.Add(path);
continue;
}
}
dirs.DropHead();
}
return classesFiles;
}
// -------------------------------------------------------------------
bool AndroidProject::IsDebug() const bool AndroidProject::IsDebug() const
{ {
return debug; return debug;

View file

@ -3,6 +3,8 @@
#include <plugin/bz2/bz2.h> #include <plugin/bz2/bz2.h>
#define METHOD_NAME "MakeBuild::" << UPP_FUNCTION_NAME << "(): "
#define LDUMP(x) // DUMP(x) #define LDUMP(x) // DUMP(x)
MakeBuild::MakeBuild() MakeBuild::MakeBuild()
@ -124,11 +126,21 @@ void MakeBuild::CreateHost(Host& host, const String& method, bool darkmode, bool
#ifdef PLATFORM_COCOA #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.. 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 #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++) { for(int i = 0; i < env.GetCount(); i++) {
LDUMP(env.GetKey(i)); LDUMP(env.GetKey(i));
LDUMP(env[i]); LDUMP(env[i]);
host.environment << env.GetKey(i) << '=' << env[i] << '\0'; host.environment << env.GetKey(i) << '=' << env[i] << '\0';
} }
host.environment.Cat(0); host.environment.Cat(0);
host.cmdout = &cmdout; host.cmdout = &cmdout;
} }
@ -149,43 +161,47 @@ One<Builder> MakeBuild::CreateBuilder(Host *host)
if(q < 0) { if(q < 0) {
PutConsole("Invalid builder " + builder); PutConsole("Invalid builder " + builder);
ConsoleShow(); ConsoleShow();
return NULL; return nullptr;
} }
Builder* b = (*BuilderMap().Get(builder))(); Builder* b = (*BuilderMap().Get(builder))();
b->host = host; b->host = host;
b->script = bm.Get("SCRIPT", ""); b->script = bm.Get("SCRIPT", "");
if(AndroidBuilder::GetBuildersNames().Find(builder) > -1) { if(AndroidBuilder::GetBuildersNames().Find(builder) > -1) {
AndroidBuilder* ab = dynamic_cast<AndroidBuilder*>(b); AndroidBuilder* pAb = dynamic_cast<AndroidBuilder*>(b);
ab->sdk.SetPath((bm.Get("SDK_PATH", ""))); if (!pAb) {
ab->ndk.SetPath((bm.Get("NDK_PATH", ""))); Loge() << METHOD_NAME << "Converting builder to android builder failed.";
ab->SetJdk(One<Jdk>(new Jdk(bm.Get("JDK_PATH", ""), host))); 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", ""); String platformVersion = bm.Get("SDK_PLATFORM_VERSION", "");
if(!platformVersion.IsEmpty()) if(!platformVersion.IsEmpty())
ab->sdk.SetPlatform(platformVersion); pAb->sdk.SetPlatform(platformVersion);
else else
ab->sdk.DeducePlatform(); pAb->sdk.DeducePlatform();
String buildToolsRelease = bm.Get("SDK_BUILD_TOOLS_RELEASE", ""); String buildToolsRelease = bm.Get("SDK_BUILD_TOOLS_RELEASE", "");
if(!buildToolsRelease.IsEmpty()) if(!buildToolsRelease.IsEmpty())
ab->sdk.SetBuildToolsRelease(buildToolsRelease); pAb->sdk.SetBuildToolsRelease(buildToolsRelease);
else else
ab->sdk.DeduceBuildToolsRelease(); pAb->sdk.DeduceBuildToolsRelease();
ab->ndk_blitz = bm.Get("NDK_BLITZ", "") == "1"; pAb->ndk_blitz = bm.Get("NDK_BLITZ", "") == "1";
if(bm.Get("NDK_ARCH_ARMEABI_V7A", "") == "1") if(bm.Get("NDK_ARCH_ARMEABI_V7A", "") == "1")
ab->ndkArchitectures.Add("armeabi-v7a"); pAb->ndkArchitectures.Add("armeabi-v7a");
if(bm.Get("NDK_ARCH_ARM64_V8A", "") == "1") if(bm.Get("NDK_ARCH_ARM64_V8A", "") == "1")
ab->ndkArchitectures.Add("arm64-v8a"); pAb->ndkArchitectures.Add("arm64-v8a");
if(bm.Get("NDK_ARCH_X86", "") == "1") if(bm.Get("NDK_ARCH_X86", "") == "1")
ab->ndkArchitectures.Add("x86"); pAb->ndkArchitectures.Add("x86");
if(bm.Get("NDK_ARCH_X86_64", "") == "1") if(bm.Get("NDK_ARCH_X86_64", "") == "1")
ab->ndkArchitectures.Add("x86_64"); pAb->ndkArchitectures.Add("x86_64");
ab->ndkToolchain = bm.Get("NDK_TOOLCHAIN", ""); pAb->ndkToolchain = bm.Get("NDK_TOOLCHAIN", "");
ab->ndkCppRuntime = bm.Get("NDK_CPP_RUNTIME", ""); pAb->ndkCppRuntime = bm.Get("NDK_CPP_RUNTIME", "");
ab->ndkCppFlags = bm.Get("NDK_COMMON_CPP_OPTIONS", ""); pAb->ndkCppFlags = bm.Get("NDK_COMMON_CPP_OPTIONS", "");
ab->ndkCFlags = bm.Get("NDK_COMMON_C_OPTIONS", ""); pAb->ndkCFlags = bm.Get("NDK_COMMON_C_OPTIONS", "");
b = ab; b = pAb;
} }
else { else {
// TODO: cpp builder variables only!!! // TODO: cpp builder variables only!!!
@ -595,3 +611,21 @@ String MakeBuild::GetInvalidBuildMethodError(const String& method)
{ {
return "Invalid build method " + method + " (" + GetMethodPath(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;
}

View file

@ -97,6 +97,7 @@ public:
private: private:
static String GetInvalidBuildMethodError(const String& method); static String GetInvalidBuildMethodError(const String& method);
bool IsAndroidMethod(const String& method) const;
}; };
extern bool output_per_assembly; extern bool output_per_assembly;

View file

@ -966,7 +966,6 @@ public:
void SetupAndroidMobilePlatform(Bar& bar, const AndroidSDK& androidSDK); void SetupAndroidMobilePlatform(Bar& bar, const AndroidSDK& androidSDK);
void LaunchAndroidSDKManager(const AndroidSDK& androidSDK); void LaunchAndroidSDKManager(const AndroidSDK& androidSDK);
void LaunchAndroidAVDManager(const AndroidSDK& androidSDK); void LaunchAndroidAVDManager(const AndroidSDK& androidSDK);
void LauchAndroidDeviceMonitor(const AndroidSDK& androidSDK);
void AssistMenu(Bar& menu); void AssistMenu(Bar& menu);
void BrowseMenu(Bar& menu); void BrowseMenu(Bar& menu);

View file

@ -425,9 +425,8 @@ void Ide::SetupMobilePlatforms(Bar& menu)
void Ide::SetupAndroidMobilePlatform(Bar& menu, const AndroidSDK& androidSDK) void Ide::SetupAndroidMobilePlatform(Bar& menu, const AndroidSDK& androidSDK)
{ {
menu.Add("SDK Manager", THISBACK1(LaunchAndroidSDKManager, androidSDK)); menu.Add("SDK Manager", [=] { LaunchAndroidSDKManager(androidSDK); });
menu.Add("AVD Manager", THISBACK1(LaunchAndroidAVDManager, androidSDK)); menu.Add("AVD Manager", [=] { LaunchAndroidAVDManager(androidSDK); });
menu.Add("Device monitor", THISBACK1(LauchAndroidDeviceMonitor, androidSDK));
} }
void Ide::ProjectRepo(Bar& menu) void Ide::ProjectRepo(Bar& menu)

View file

@ -573,21 +573,10 @@ void Ide::RemoveDs()
void Ide::LaunchAndroidSDKManager(const AndroidSDK& androidSDK) void Ide::LaunchAndroidSDKManager(const AndroidSDK& androidSDK)
{ {
Host host; PromptOK("SDK managment is not yet implemented in TheIDE. Use Android Studio for this purpose instead.");
CreateHost(host, darkmode, disable_uhd);
IGNORE_RESULT(host.Execute(androidSDK.GetLauchSDKManagerCmd()));
} }
void Ide::LaunchAndroidAVDManager(const AndroidSDK& androidSDK) void Ide::LaunchAndroidAVDManager(const AndroidSDK& androidSDK)
{ {
Host host; PromptOK("AVD managment is not yet implemented in TheIDE. Use Android Studio for this purpose instead.");
CreateHost(host, darkmode, disable_uhd);
IGNORE_RESULT(host.Execute(androidSDK.GetLauchAVDManagerCmd()));
}
void Ide::LauchAndroidDeviceMonitor(const AndroidSDK& androidSDK)
{
Host host;
CreateHost(host, darkmode, disable_uhd);
IGNORE_RESULT(host.Execute(androidSDK.MonitorPath()));
} }