Browse Source

Merge pull request #476 from AtomicGameEngine/JME-ATOMIC-74

Build (failure) improvements
JoshEngebretson 10 years ago
parent
commit
79f6adfe48

+ 1 - 1
Script/AtomicEditor/ui/modal/build/BuildOutput.ts

@@ -59,7 +59,7 @@ class BuildOutput extends ModalWindow {
         return false;
     }
 
-    textOutput: string;
+    textOutput: string = "";
     buildBase: ToolCore.BuildBase;
     outputField: Atomic.UIEditField;
 

+ 5 - 5
Source/ToolCore/Build/BuildAndroid.cpp

@@ -67,7 +67,7 @@ void BuildAndroid::RunADBStartActivity()
     Subprocess* subprocess = subs->Launch(adbCommand, args, buildPath_);
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunStartActivity");
+        FailBuild("BuildFailed::RunStartActivity");
         return;
     }
 
@@ -110,7 +110,7 @@ void BuildAndroid::RunADBInstall()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunADBInstall");
+        FailBuild("BuildFailed::RunADBInstall");
         return;
     }
 
@@ -194,7 +194,7 @@ void BuildAndroid::RunADBListDevices()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunADBListDevices");
+        FailBuild("BuildFailed::RunADBListDevices");
         return;
     }
 
@@ -251,7 +251,7 @@ void BuildAndroid::RunAntDebug()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunAntDebug");
+        FailBuild("BuildFailed::RunAntDebug");
         return;
     }
 
@@ -338,7 +338,7 @@ void BuildAndroid::Build(const String& buildPath)
 
     if (!gen.Generate())
     {
-        SendBuildFailure(gen.GetErrorText());
+        FailBuild(gen.GetErrorText());
         return;
     }
 

+ 176 - 9
Source/ToolCore/Build/BuildBase.cpp

@@ -12,6 +12,7 @@
 #include "../Project/Project.h"
 #include "../ToolEnvironment.h"
 
+#include "BuildSystem.h"
 #include "BuildEvents.h"
 #include "BuildBase.h"
 #include "ResourcePackager.h"
@@ -21,7 +22,8 @@ namespace ToolCore
 
 BuildBase::BuildBase(Context * context, Project* project, PlatformID platform) : Object(context),
     platformID_(platform),
-    containsMDL_(false)
+    containsMDL_(false),
+    buildFailed_(false)
 {
     if (UseResourcePackager())
         resourcePackager_ = new ResourcePackager(context, this);
@@ -38,28 +40,193 @@ BuildBase::~BuildBase()
     }
 }
 
-void BuildBase::BuildLog(const String& message)
+#ifdef ATOMIC_PLATFORM_WINDOWS
+
+bool BuildBase::BuildClean(const String& path)
+{
+    if (buildFailed_)
+    {
+        LOGERRORF("BuildBase::BuildClean - Attempt to clean directory of failed build, %s", path.CString());
+        return false;
+    }
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    if (!fileSystem->DirExists(path))
+        return true;
+
+    // On Windows, do a little dance with the folder to avoid issues
+    // with deleting folder and immediately recreating it
+
+    String pathName, fileName, ext;
+    SplitPath(path, pathName, fileName, ext);
+    pathName = AddTrailingSlash(pathName);    
+
+    unsigned i = 0;
+    while (true) 
+    {
+        String newPath = ToString("%s%s_Temp_%u", pathName.CString(), fileName.CString(), i++);
+        if (!fileSystem->DirExists(newPath))
+        {
+            if (!MoveFileExW(GetWideNativePath(path).CString(), GetWideNativePath(newPath).CString(), MOVEFILE_WRITE_THROUGH))
+            {
+                FailBuild(ToString("BuildBase::BuildClean: Unable to move directory %s -> ", path.CString(), newPath.CString()));
+                return false;
+            }
+
+            // Remove the moved directory
+            return BuildRemoveDirectory(newPath);
+
+        }
+        else
+        {
+            LOGWARNINGF("BuildBase::BuildClean - temp build folder exists, removing: %s", newPath.CString());
+            fileSystem->RemoveDir(newPath, true);
+        }
+
+        if (i == 255)
+        {
+            FailBuild(ToString("BuildBase::BuildClean: Unable to move directory ( i == 255) %s -> ", path.CString(), newPath.CString()));
+            return false;
+        }
+    }
+
+    return false;
+}
+
+#else
+
+bool BuildBase::BuildClean(const String& path)
+{
+    return BuildRemoveDirectory(path);
+}
+
+#endif
+
+bool BuildBase::BuildCreateDirectory(const String& path)
+{
+    if (buildFailed_)
+    {
+        LOGERRORF("BuildBase::BuildCreateDirectory - Attempt to create directory of failed build, %s", path.CString());
+        return false;
+    }
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    if (fileSystem->DirExists(path))
+        return true;
+
+    bool result = fileSystem->CreateDir(path);
+
+    if (!result)
+    {
+        FailBuild(ToString("BuildBase::BuildCreateDirectory: Unable to create directory %s", path.CString()));
+        return false;
+    }
+
+    return true;
+
+}
+
+bool BuildBase::BuildCopyFile(const String& srcFileName, const String& destFileName)
+{
+    if (buildFailed_)
+    {
+        LOGERRORF("BuildBase::BuildCopyFile - Attempt to copy file of failed build, %s", srcFileName.CString());
+        return false;
+    }
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+
+    bool result = fileSystem->Copy(srcFileName, destFileName);
+
+    if (!result)
+    {
+        FailBuild(ToString("BuildBase::BuildCopyFile: Unable to copy file %s -> %s", srcFileName.CString(), destFileName.CString()));
+        return false;
+    }
+
+    return true;
+}
+
+bool BuildBase::BuildRemoveDirectory(const String& path)
+{
+    if (buildFailed_)
+    {
+        LOGERRORF("BuildBase::BuildRemoveDirectory - Attempt to remove directory of failed build, %s", path.CString());
+        return false;
+    }
+
+    FileSystem* fileSystem = GetSubsystem<FileSystem>();
+    if (!fileSystem->DirExists(path))
+        return true;
+
+    bool result = fileSystem->RemoveDir(path, true);
+
+    if (!result)
+    {
+        FailBuild(ToString("BuildBase::BuildRemoveDirectory: Unable to remove directory %s", path.CString()));
+        return false;
+    }
+
+    return true;
+}
+
+void BuildBase::BuildLog(const String& message, bool sendEvent)
 {
     buildLog_.Push(message);
+
+    if (sendEvent)
+    {
+        String colorMsg = ToString("<color #D4FB79>%s</color>\n", message.CString());
+        VariantMap buildOutput;
+        buildOutput[BuildOutput::P_TEXT] = colorMsg;
+        SendEvent(E_BUILDOUTPUT, buildOutput);
+    }
+
 }
 
-void BuildBase::BuildWarn(const String& warning)
+void BuildBase::BuildWarn(const String& warning, bool sendEvent)
 {
     buildWarnings_.Push(warning);
+
+    if (sendEvent)
+    {
+        String colorMsg = ToString("<color #FFFF00>%s</color>\n", warning.CString());
+        VariantMap buildOutput;
+        buildOutput[BuildOutput::P_TEXT] = colorMsg;
+        SendEvent(E_BUILDOUTPUT, buildOutput);
+    }
+
 }
 
-void BuildBase::BuildError(const String& error)
+void BuildBase::BuildError(const String& error, bool sendEvent)
 {
     buildErrors_.Push(error);
+
+    if (sendEvent)
+    {
+        String colorMsg = ToString("<color #FF0000>%s</color>\n", error.CString());
+        VariantMap buildOutput;
+        buildOutput[BuildOutput::P_TEXT] = colorMsg;
+        SendEvent(E_BUILDOUTPUT, buildOutput);
+    }
 }
 
-void BuildBase::SendBuildFailure(const String& message)
+void BuildBase::FailBuild(const String& message)
 {
+    if (buildFailed_)
+    {
+        LOGERRORF("BuildBase::FailBuild - Attempt to fail already failed build: %s", message.CString());
+        return;
+    }
+
+    buildFailed_ = true;
+
+    BuildError(message);
 
-    VariantMap buildError;
-    buildError[BuildComplete::P_PLATFORMID] = platformID_;
-    buildError[BuildComplete::P_MESSAGE] = message;
-    SendEvent(E_BUILDCOMPLETE, buildError);
+    BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
+    buildSystem->BuildComplete(platformID_, buildPath_, false, message);
 
 }
 

+ 13 - 5
Source/ToolCore/Build/BuildBase.h

@@ -39,16 +39,23 @@ public:
     // will warn on name conflicts
     void AddResourceDir(const String& dir);
 
-    void BuildLog(const String& message);
-    void BuildWarn(const String& warning);
-    void BuildError(const String& error);
+    void BuildLog(const String& message, bool sendEvent = true);
+    void BuildWarn(const String& warning, bool sendEvent = true);
+    void BuildError(const String& error, bool sendEvent = true);
+
+    /// Fail the current build
+    void FailBuild(const String& message);
 
     /// Converts subprocess output event to a buildoutput event
     void HandleSubprocessOutputEvent(StringHash eventType, VariantMap& eventData);
 
 protected:
 
-    void SendBuildFailure(const String& message);
+    bool BuildClean(const String& path);
+    bool BuildRemoveDirectory(const String& path);
+    bool BuildCreateDirectory(const String& path);
+    bool BuildCopyFile(const String& srcFileName, const String& destFileName);
+
 
     void GenerateResourcePackage(const String& resourcePackagePath);
 
@@ -60,11 +67,12 @@ protected:
     PODVector<BuildResourceEntry*> resourceEntries_;
 
     bool containsMDL_;
+    bool buildFailed_;
 
 private:
 
     PlatformID platformID_;
-
+    
     Vector<String> buildLog_;
     Vector<String> buildWarnings_;
     Vector<String> buildErrors_;

+ 3 - 3
Source/ToolCore/Build/BuildIOS.cpp

@@ -160,7 +160,7 @@ void BuildIOS::RunConvertPList()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunConvertPList");
+        FailBuild("BuildFailed::RunConvertPList");
         return;
     }
 
@@ -210,7 +210,7 @@ void BuildIOS::RunCodeSign()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunCodeSign");
+        FailBuild("BuildFailed::RunCodeSign");
         return;
     }
 
@@ -259,7 +259,7 @@ void BuildIOS::RunDeploy()
 
     if (!subprocess)
     {
-        SendBuildFailure("BuildFailed::RunDeploy");
+        FailBuild("BuildFailed::RunDeploy");
         return;
     }
 

+ 22 - 16
Source/ToolCore/Build/BuildMac.cpp

@@ -58,37 +58,44 @@ void BuildMac::Build(const String& buildPath)
 
     buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();
 
-    VariantMap buildOutput;
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Starting Mac Deployment</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
+    BuildLog("Starting Mac Deployment");
 
     Initialize();
 
     BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
 
+    if (!BuildRemoveDirectory(buildPath_))
+        return;
+
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
-    if (fileSystem->DirExists(buildPath_))
-        fileSystem->RemoveDir(buildPath_, true);
 
     String appSrcPath = tenv->GetPlayerAppFolder();
 
-    fileSystem->CreateDir(buildPath_);
+    if (!BuildCreateDirectory(buildPath_))
+        return;
 
     buildPath_ += "/AtomicPlayer.app";
 
-    fileSystem->CreateDir(buildPath_);
-
-    fileSystem->CreateDir(buildPath_ + "/Contents");
-    fileSystem->CreateDir(buildPath_ + "/Contents/MacOS");
-    fileSystem->CreateDir(buildPath_ + "/Contents/Resources");
+    if (!BuildCreateDirectory(buildPath_))
+        return;
+    if (!BuildCreateDirectory(buildPath_ + "/Contents"))
+        return;
+    if (!BuildCreateDirectory(buildPath_ + "/Contents/MacOS"))
+        return;
+    if (!BuildCreateDirectory(buildPath_ + "/Contents/Resources"))
+        return;
 
     String resourcePackagePath = buildPath_ + "/Contents/Resources/AtomicResources" + PAK_EXTENSION;
     GenerateResourcePackage(resourcePackagePath);
 
-    fileSystem->Copy(appSrcPath + "/Contents/Resources/Atomic.icns", buildPath_ + "/Contents/Resources/Atomic.icns");
+    if (!BuildCopyFile(appSrcPath + "/Contents/Resources/Atomic.icns", buildPath_ + "/Contents/Resources/Atomic.icns"))
+        return;
+
+    if (!BuildCopyFile(appSrcPath + "/Contents/Info.plist", buildPath_ + "/Contents/Info.plist"))
+        return;
 
-    fileSystem->Copy(appSrcPath + "/Contents/Info.plist", buildPath_ + "/Contents/Info.plist");
-    fileSystem->Copy(appSrcPath + "/Contents/MacOS/AtomicPlayer", buildPath_ + "/Contents/MacOS/AtomicPlayer");
+    if (!BuildCopyFile(appSrcPath + "/Contents/MacOS/AtomicPlayer", buildPath_ + "/Contents/MacOS/AtomicPlayer"))
+        return;
 
 #ifdef ATOMIC_PLATFORM_OSX
     Vector<String> args;
@@ -97,8 +104,7 @@ void BuildMac::Build(const String& buildPath)
     fileSystem->SystemRun("chmod", args);
 #endif
 
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Mac Deployment Complete</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
+    BuildLog("Mac Deployment Complete");
 
     buildPath_ = buildPath + "/Mac-Build";
     buildSystem->BuildComplete(PLATFORMID_MAC, buildPath_);

+ 19 - 18
Source/ToolCore/Build/BuildWindows.cpp

@@ -76,6 +76,8 @@ void BuildWindows::BuildAtomicNET()
     if (!results.Size())
         return;
 
+    BuildLog("Building AtomicNET");
+
     fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET");
     fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET/Atomic");
     fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources/AtomicNET/Atomic/Assemblies");
@@ -124,42 +126,41 @@ void BuildWindows::Build(const String& buildPath)
 
     buildPath_ = AddTrailingSlash(buildPath) + GetBuildSubfolder();
 
-    VariantMap buildOutput;
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Starting Windows Deployment</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
+    BuildLog("Starting Windows Deployment");
 
     Initialize();
 
+    if (!BuildClean(buildPath_))
+        return;
+
     BuildSystem* buildSystem = GetSubsystem<BuildSystem>();
 
     FileSystem* fileSystem = GetSubsystem<FileSystem>();
 
-    if (fileSystem->DirExists(buildPath_))
-        fileSystem->RemoveDir(buildPath_, true);
-
     String rootSourceDir = tenv->GetRootSourceDir();
     String playerBinary = tenv->GetPlayerBinary();
     String d3d9dll = GetPath(playerBinary) + "/D3DCompiler_47.dll";
 
-    fileSystem->CreateDir(buildPath_);
-    fileSystem->CreateDir(buildPath_ + "/AtomicPlayer_Resources");
+    if (!BuildCreateDirectory(buildPath_))
+        return;
+
+    if (!BuildCreateDirectory(buildPath_ + "/AtomicPlayer_Resources"))
+        return;
 
     String resourcePackagePath = buildPath_ + "/AtomicPlayer_Resources/AtomicResources" + PAK_EXTENSION;
     GenerateResourcePackage(resourcePackagePath);
+    if (buildFailed_)
+        return;
+   
+    if (!BuildCopyFile(playerBinary, buildPath_ + "/AtomicPlayer.exe"))
+        return;
 
-    fileSystem->Copy(playerBinary, buildPath_ + "/AtomicPlayer.exe");
-    fileSystem->Copy(d3d9dll, buildPath_ + "/D3DCompiler_47.dll");
-
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Building AtomicNET</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
+    if (!BuildCopyFile(d3d9dll, buildPath_ + "/D3DCompiler_47.dll"))
+        return;
 
     BuildAtomicNET();
 
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Building AtomicNET Complete</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
-
-    buildOutput[BuildOutput::P_TEXT] = "\n\n<color #D4FB79>Windows Deployment Complete</color>\n\n";
-    SendEvent(E_BUILDOUTPUT, buildOutput);
+    BuildLog("Windows Deployment Complete");
 
     buildSystem->BuildComplete(PLATFORMID_WINDOWS, buildPath_);
 

+ 8 - 7
Source/ToolCore/Build/ResourcePackager.cpp

@@ -55,12 +55,12 @@ ResourcePackager::~ResourcePackager()
 
 bool ResourcePackager::WritePackageFile(const String& destFilePath)
 {
-    buildBase_->BuildLog("Writing package");
+    buildBase_->BuildLog("Writing package", false);
 
     SharedPtr<File> dest(new File(context_, destFilePath, FILE_WRITE));
     if (!dest->IsOpen())
     {
-        buildBase_->BuildError("Could not open output file " + destFilePath);
+        buildBase_->FailBuild("Could not open output file " + destFilePath);
         return false;
     }
 
@@ -90,7 +90,7 @@ bool ResourcePackager::WritePackageFile(const String& destFilePath)
         File srcFile(context_, entry->absolutePath_);
         if (!srcFile.IsOpen())
         {
-            buildBase_->BuildError("Could not open input file " + entry->absolutePath_);
+            buildBase_->FailBuild("Could not open input file " + entry->absolutePath_);
             return false;
         }
 
@@ -100,7 +100,7 @@ bool ResourcePackager::WritePackageFile(const String& destFilePath)
 
         if (srcFile.Read(&buffer[0], dataSize) != dataSize)
         {
-            buildBase_->BuildError("Could not read input file " + entry->absolutePath_);
+            buildBase_->FailBuild("Could not read input file " + entry->absolutePath_);
             return false;
         }
 
@@ -137,7 +137,7 @@ bool ResourcePackager::WritePackageFile(const String& destFilePath)
             unsigned packedSize = LZ4_compressHC((const char*)&buffer[pos], (char*)compressBuffer.Get(), unpackedSize);
             if (!packedSize)
             {
-                buildBase_->BuildError("LZ4 compression failed for file " + entry->absolutePath_ + " at offset " + pos);
+                buildBase_->FailBuild("LZ4 compression failed for file " + entry->absolutePath_ + " at offset " + pos);
                 return false;
             }
 
@@ -149,7 +149,7 @@ bool ResourcePackager::WritePackageFile(const String& destFilePath)
             pos += unpackedSize;
         }
 
-        buildBase_->BuildLog(entry->absolutePath_ + " in " + String(dataSize) + " out " + String(totalPackedBytes));
+        buildBase_->BuildLog(entry->absolutePath_ + " in " + String(dataSize) + " out " + String(totalPackedBytes), false);
         }
     //}
 
@@ -171,6 +171,7 @@ bool ResourcePackager::WritePackageFile(const String& destFilePath)
         dest->WriteUInt(entry->checksum_);
     }
 
+    buildBase_->BuildLog("Resource Package:");
     buildBase_->BuildLog("Number of files " + String(resourceEntries_.Size()));
     buildBase_->BuildLog("File data size " + String(totalDataSize));
     buildBase_->BuildLog("Package size " + String(dest->GetSize()));
@@ -196,7 +197,7 @@ void ResourcePackager::GeneratePackage(const String& destFilePath)
 
         if (!file.Open(entry->absolutePath_))
         {
-            buildBase_->BuildError(Atomic::ToString("Could not open resource file %s", entry->absolutePath_.CString()));
+            buildBase_->FailBuild(Atomic::ToString("Could not open resource file %s", entry->absolutePath_.CString()));
             return;
         }