Browse Source

Android project generator and build system

Josh Engebretson 10 years ago
parent
commit
ed90ee1a18

+ 1 - 0
Rakefile

@@ -136,6 +136,7 @@ namespace :build  do
       Dir.chdir(CMAKE_ANDROID_BUILD_FOLDER) do
       Dir.chdir(CMAKE_ANDROID_BUILD_FOLDER) do
 
 
         sh "#{ATOMICTOOL_BIN_MACOSX} bind #{$RAKE_ROOT} Script/Packages/Atomic/ ANDROID"
         sh "#{ATOMICTOOL_BIN_MACOSX} bind #{$RAKE_ROOT} Script/Packages/Atomic/ ANDROID"
+        sh "#{ATOMICTOOL_BIN_MACOSX} bind #{$RAKE_ROOT} Script/Packages/AtomicPlayer/ ANDROID"
         sh "cmake -DCMAKE_TOOLCHAIN_FILE=#{$RAKE_ROOT}/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ../../"
         sh "cmake -DCMAKE_TOOLCHAIN_FILE=#{$RAKE_ROOT}/CMake/Toolchains/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release ../../"
         sh "make -j4"
         sh "make -j4"
       end
       end

+ 1 - 1
Script/Packages/ToolCore/ToolCore.json

@@ -9,7 +9,7 @@
 							 "Asset", "AssetDatabase", "AssetImporter", "AudioImporter", "ModelImporter", "MaterialImporter", "AnimationImportInfo",
 							 "Asset", "AssetDatabase", "AssetImporter", "AudioImporter", "ModelImporter", "MaterialImporter", "AnimationImportInfo",
 							 "PrefabImporter", "JavascriptImporter", "TextureImporter", "SpriterImporter", "PEXImporter", "LicenseSystem",
 							 "PrefabImporter", "JavascriptImporter", "TextureImporter", "SpriterImporter", "PEXImporter", "LicenseSystem",
 						 	 "ProjectUserPrefs", "ProjectBuildSettings",
 						 	 "ProjectUserPrefs", "ProjectBuildSettings",
-						 	 "BuildBase", "BuildSystem", "BuildMac", "BuildWeb", "BuildWindows",
+						 	 "BuildBase", "BuildSystem", "BuildMac", "BuildWeb", "BuildWindows", "BuildAndroid",
 						 	 "ProjectBuildSettings", "MacBuildSettings", "WindowsBuildSettings", "WebBuildSettings", "AndroidBuildSettings", "MacBuildSettings"],
 						 	 "ProjectBuildSettings", "MacBuildSettings", "WindowsBuildSettings", "WebBuildSettings", "AndroidBuildSettings", "MacBuildSettings"],
 	"typescript_decl" : {
 	"typescript_decl" : {
 
 

+ 1 - 1
Source/AtomicPlayer/Application/AtomicPlayer.cpp

@@ -67,7 +67,7 @@ void AtomicPlayerApp::Setup()
 
 
 #if (ATOMIC_PLATFORM_ANDROID)
 #if (ATOMIC_PLATFORM_ANDROID)
     engineParameters_["FullScreen"] = true;
     engineParameters_["FullScreen"] = true;
-    engineParameters_["ResourcePaths"] = "CoreData;AtomicResources";
+    engineParameters_["ResourcePaths"] = "CoreData;PlayerData;Cache;AtomicResources";
 #elif ATOMIC_PLATFORM_WEB
 #elif ATOMIC_PLATFORM_WEB
     engineParameters_["FullScreen"] = false;
     engineParameters_["FullScreen"] = false;
     engineParameters_["ResourcePaths"] = "AtomicResources";
     engineParameters_["ResourcePaths"] = "AtomicResources";

+ 253 - 0
Source/ToolCore/Build/AndroidProjectGenerator.cpp

@@ -0,0 +1,253 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include <Poco/File.h>
+
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/IO/File.h>
+
+#include "../ToolSystem.h"
+#include "../ToolEnvironment.h"
+#include "../Project/Project.h"
+#include "../Project/ProjectBuildSettings.h"
+#include "BuildMac.h"
+#include "BuildSystem.h"
+
+#include "AndroidProjectGenerator.h"
+
+namespace ToolCore
+{
+
+AndroidProjectGenerator::AndroidProjectGenerator(Context* context) :
+    Object(context)
+{
+
+}
+
+AndroidProjectGenerator::~AndroidProjectGenerator()
+{
+
+}
+
+bool AndroidProjectGenerator::Generate()
+{
+    if (!GenerateAndroidManifest())
+        return false;
+
+    if (!GenerateStringXML())
+        return false;
+
+    if (!GenerateLocalProperties())
+        return false;
+
+    if (!GenerateProjectProperties())
+        return false;
+
+    if (!GenerateActivitySource())
+        return false;
+
+    return true;
+}
+
+bool AndroidProjectGenerator::GenerateActivitySource()
+{
+    ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+    Project* project = toolSystem->GetProject();
+    AndroidBuildSettings* settings = project->GetBuildSettings()->GetAndroidBuildSettings();
+
+    String packageName = settings->GetPackageName();
+
+    if (!packageName.Length())
+    {
+        errorText_ = "Invalid Package Name";
+        return false;
+    }
+
+    Vector<String> elements = settings->GetPackageName().Split('.');
+    String path;
+    path.Join(elements, "/");
+
+    path = buildPath_ + "/src/" + path;
+
+    Poco::File dirs(path.CString());
+    dirs.createDirectories();
+
+    if (!dirs.exists())
+    {
+        errorText_ = "Unable to create ";
+        return false;
+    }
+
+    String source;
+    source.AppendWithFormat("package %s;\n", packageName.CString());
+
+    source += "import org.libsdl.app.SDLActivity;\n";
+
+    source += "public class AtomicGameEngine extends SDLActivity {\n";
+
+    source += "}\n";
+
+    File file(context_, path + "/AtomicGameEngine.java", FILE_WRITE);
+
+    if (!file.IsOpen())
+        return false;
+
+    file.Write(source.CString(), source.Length());
+
+    return true;
+
+}
+
+bool AndroidProjectGenerator::GenerateLocalProperties()
+{
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    ToolPrefs* prefs = tenv->GetToolPrefs();
+    String sdkPath = prefs->GetAndroidSDKPath();
+
+    if (!sdkPath.Length())
+    {
+        errorText_ = "Invalid Android SDK Path";
+        return false;
+    }
+
+    String props;
+    props.AppendWithFormat("sdk.dir=%s", sdkPath.CString());
+
+    File file(context_, buildPath_ + "/local.properties", FILE_WRITE);
+
+    if (!file.IsOpen())
+        return false;
+
+    file.Write(props.CString(), props.Length());
+
+    return true;
+
+}
+
+bool AndroidProjectGenerator::GenerateProjectProperties()
+{
+    ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+    Project* project = toolSystem->GetProject();
+    AndroidBuildSettings* settings = project->GetBuildSettings()->GetAndroidBuildSettings();
+
+    String apiString = settings->GetSDKVersion();
+
+    if (!apiString.Length())
+    {
+        errorText_ = "Invalid Android API";
+        return false;
+    }
+
+
+    String props;
+    props.AppendWithFormat("target=%s", apiString.CString());
+
+    File file(context_, buildPath_ + "/project.properties", FILE_WRITE);
+
+    if (!file.IsOpen())
+        return false;
+
+    file.Write(props.CString(), props.Length());
+
+    return true;
+
+}
+
+bool AndroidProjectGenerator::GenerateStringXML()
+{
+    ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+    Project* project = toolSystem->GetProject();
+    AndroidBuildSettings* settings = project->GetBuildSettings()->GetAndroidBuildSettings();
+
+    String appName = settings->GetAppName();
+
+    if (!appName.Length())
+    {
+        errorText_ = "Invalid App Name";
+        return false;
+    }
+
+    String strings  = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+
+    strings += "<resources>\n";
+
+    strings.AppendWithFormat("<string name=\"app_name\">%s</string>\n", appName.CString());
+
+    strings += "</resources>\n";
+
+    File file(context_, buildPath_ + "/res/values/strings.xml", FILE_WRITE);
+
+    if (!file.IsOpen())
+        return false;
+
+    file.Write(strings.CString(), strings.Length());
+
+    return true;
+
+}
+
+bool AndroidProjectGenerator::GenerateAndroidManifest()
+{
+    ToolSystem* toolSystem = GetSubsystem<ToolSystem>();
+    Project* project = toolSystem->GetProject();
+    AndroidBuildSettings* settings = project->GetBuildSettings()->GetAndroidBuildSettings();
+
+    String package = settings->GetPackageName();
+
+
+    if (!package.Length())
+    {
+        errorText_ = "Invalid Package Name";
+        return false;
+    }
+
+    // TODO: from settings
+    String activityName = "AtomicGameEngine";
+    if (!activityName.Length())
+    {
+        errorText_ = "Invalid Activity Name";
+        return false;
+    }
+
+    String manifest  = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+    manifest += "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n";
+    manifest.AppendWithFormat("package=\"%s\"\n", package.CString());
+    manifest += "android:versionCode=\"1\"\n";
+    manifest += "android:versionName=\"1.0\">\n";
+
+    manifest += "<uses-permission android:name=\"android.permission.INTERNET\" />\n";
+    manifest += "<uses-feature android:glEsVersion=\"0x00020000\" />\n";
+    manifest += "<uses-sdk android:targetSdkVersion=\"12\" android:minSdkVersion=\"10\" />\n";
+
+    manifest += "<application android:label=\"@string/app_name\" android:icon=\"@drawable/icon\">\n";
+    manifest.AppendWithFormat("<activity android:name=\".%s\"\n", activityName.CString());
+
+    manifest += "android:label=\"@string/app_name\"\n";
+    manifest += "android:theme=\"@android:style/Theme.NoTitleBar.Fullscreen\"\n";
+    manifest += "android:configChanges=\"keyboardHidden|orientation\"\n";
+    manifest += "android:screenOrientation=\"landscape\">\n";
+    manifest += "<intent-filter>\n";
+    manifest += "<action android:name=\"android.intent.action.MAIN\" />\n";
+    manifest += "<category android:name=\"android.intent.category.LAUNCHER\" />\n";
+    manifest += "</intent-filter>\n";
+    manifest += "</activity>\n";
+    manifest += "</application>\n";
+    manifest += "</manifest>\n";
+
+    File file(context_, buildPath_ + "/AndroidManifest.xml", FILE_WRITE);
+
+    if (!file.IsOpen())
+        return false;
+
+    file.Write(manifest.CString(), manifest.Length());
+
+    return true;
+
+}
+
+}
+
+/*
+
+*/

+ 46 - 0
Source/ToolCore/Build/AndroidProjectGenerator.h

@@ -0,0 +1,46 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+#include <Atomic/Core/Object.h>
+
+#include "BuildSettings.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class AndroidProjectGenerator : public Object
+{
+
+    OBJECT(AndroidProjectGenerator);
+
+public:
+
+    AndroidProjectGenerator(Context* context);
+    virtual ~AndroidProjectGenerator();
+
+    void SetBuildPath(const String& buildpath) { buildPath_ = buildpath; }
+
+    bool Generate();
+
+    const String& GetErrorText() { return errorText_; }
+
+private:
+
+    bool GenerateAndroidManifest();
+    bool GenerateStringXML();
+    bool GenerateLocalProperties();
+    bool GenerateProjectProperties();
+    bool GenerateActivitySource();
+
+    String buildPath_;
+    String errorText_;
+
+};
+
+}

+ 115 - 0
Source/ToolCore/Build/BuildAndroid.cpp

@@ -0,0 +1,115 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include <Atomic/Core/StringUtils.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/IO/File.h>
+
+#include "../ToolSystem.h"
+#include "../ToolEnvironment.h"
+#include "../Project/Project.h"
+
+#include "AndroidProjectGenerator.h"
+
+#include "BuildSystem.h"
+#include "BuildAndroid.h"
+
+namespace ToolCore
+{
+
+BuildAndroid::BuildAndroid(Context* context, Project* project) : BuildBase(context, project)
+{
+
+}
+
+BuildAndroid::~BuildAndroid()
+{
+
+}
+
+void BuildAndroid::Initialize()
+{
+    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+    Project* project = tsystem->GetProject();
+
+    Vector<String> defaultResourcePaths;
+    GetDefaultResourcePaths(defaultResourcePaths);
+    String projectResources = project->GetResourcePath();
+
+    for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
+    {
+        AddResourceDir(defaultResourcePaths[i]);
+    }
+
+    // TODO: smart filtering of cache
+    AddResourceDir(project->GetProjectPath() + "Cache/");
+    AddResourceDir(projectResources);
+
+    BuildResourceEntries();
+}
+void BuildAndroid::Build(const String& buildPath)
+{
+    ToolEnvironment* tenv = GetSubsystem<ToolEnvironment>();
+    ToolSystem* tsystem = GetSubsystem<ToolSystem>();
+    Project* project = tsystem->GetProject();
+
+    buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();
+
+    Initialize();
+
+    //generate manifest file
+    String manifest;
+    for (unsigned i = 0; i < resourceEntries_.Size(); i++)
+    {
+        BuildResourceEntry* entry = resourceEntries_[i];
+        manifest += entry->packagePath_;
+        if ( i != resourceEntries_.Size() - 1)
+            manifest += ";";
+    }
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    if (fileSystem->DirExists(buildPath_))
+        fileSystem->RemoveDir(buildPath_, true);
+
+    String buildSourceDir = tenv->GetToolDataDir();
+
+    String androidProject = buildSourceDir + "Deployment/Android";
+
+    // Copy the base android project
+    fileSystem->CopyDir(androidProject, buildPath_);
+
+    Vector<String> defaultResourcePaths;
+    GetDefaultResourcePaths(defaultResourcePaths);
+    String projectResources = project->GetResourcePath();
+
+    for (unsigned i = 0; i < defaultResourcePaths.Size(); i++)
+    {
+        fileSystem->CopyDir(defaultResourcePaths[i], buildPath_ + "/assets/" + GetFileName(RemoveTrailingSlash(defaultResourcePaths[i])));
+    }
+
+    fileSystem->CopyDir(project->GetProjectPath() + "Cache/", buildPath_ + "/assets/Cache");
+    fileSystem->CopyDir(projectResources, buildPath_ + "/assets/AtomicResources");
+
+    // write the manifest
+    SharedPtr<File> mfile(new File(context_, buildPath_ + "/assets/AtomicManifest", FILE_WRITE));
+    mfile->WriteString(manifest);
+    mfile->Close();
+
+
+    AndroidProjectGenerator gen(context_);
+    gen.SetBuildPath(buildPath_);
+
+    if (!gen.Generate())
+    {
+        return;
+    }
+
+    BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
+    buildSystem->BuildComplete(PLATFORMID_ANDROID, buildPath_);
+
+    //fileSystem->SystemCommandAsync("/Applications/Firefox.app/Contents/MacOS/firefox");
+
+}
+
+}

+ 34 - 0
Source/ToolCore/Build/BuildAndroid.h

@@ -0,0 +1,34 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include "BuildBase.h"
+
+namespace ToolCore
+{
+
+class Project;
+
+class BuildAndroid : public BuildBase
+{
+    OBJECT(BuildAndroid);
+
+public:
+
+    BuildAndroid(Context* context, Project* project);
+    virtual ~BuildAndroid();
+
+    void Build(const String& buildPath);
+
+    String GetBuildSubfolder() { return "Android-Build"; }
+
+protected:
+
+    void Initialize();
+
+
+};
+
+}

+ 2 - 1
Source/ToolCore/Platform/PlatformAndroid.cpp

@@ -4,6 +4,7 @@
 
 
 #include "../ToolEnvironment.h"
 #include "../ToolEnvironment.h"
 #include "../Subprocess/SubprocessSystem.h"
 #include "../Subprocess/SubprocessSystem.h"
+#include "../Build/BuildAndroid.h"
 
 
 #include "PlatformAndroid.h"
 #include "PlatformAndroid.h"
 
 
@@ -22,7 +23,7 @@ PlatformAndroid::~PlatformAndroid()
 
 
 BuildBase* PlatformAndroid::NewBuild(Project *project)
 BuildBase* PlatformAndroid::NewBuild(Project *project)
 {
 {
-    return 0;
+    return new BuildAndroid(context_, project);
 }
 }
 
 
 void PlatformAndroid::PrependAndroidCommandArgs(Vector<String> args)
 void PlatformAndroid::PrependAndroidCommandArgs(Vector<String> args)