Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added Unity build tasks to BuildTasksContainer #31

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.Callbacks;
using UnityEditorInternal;
using UnityEngine;

namespace StansAssets.Build.Meta.Editor
{
class BuildProcessor : IPreprocessBuildWithReport
class BuildProcessor : IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
const int k_CallbackOrder = 1;
static readonly string k_BuildMetadataPath = $"Assets/Resources/{nameof(BuildMetadata)}.asset";
Expand Down Expand Up @@ -43,9 +42,8 @@ public void OnPreprocessBuild(BuildReport report)

SaveBuildMetadata(buildMetadata);
}

[PostProcessBuild(k_CallbackOrder)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)

public void OnPostprocessBuild(BuildReport report)
{
DeleteBuildMetadata();
if (s_IncrementBuildNumberEnable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ static void SaveBuildMetadata(BuildMetadata buildMetadata, BuildTarget buildTarg
var buildNumber = 0;
if (versionsSheet == null)
{
spreadsheet.CreateGoogleSheet(sheetName);
spreadsheet.CreateGoogleSheet(new GoogleSheet.SheetProperties
{
Title = sheetName
});
spreadsheet.AppendGoogleCell(rangeAppend, s_Headers);
if (spreadsheet.SyncErrorMassage != null)
{
Expand Down
3 changes: 3 additions & 0 deletions com.stansassets.build/BuildPipeline/Common.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions com.stansassets.build/BuildPipeline/Common/ListExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;

namespace StansAssets.Build.Pipeline
{
public static class ListExtensions
{
// borrowed from https://stackoverflow.com/a/22801345
public static void AddSorted<T>(this List<T> @this, T item) where T : IComparable<T>
{
if (@this.Count == 0)
{
@this.Add(item);
return;
}

if (@this[@this.Count - 1].CompareTo(item) <= 0)
{
@this.Add(item);
return;
}

if (@this[0].CompareTo(item) >= 0)
{
@this.Insert(0, item);
return;
}

var index = @this.BinarySearch(item);
if (index < 0)
index = ~index;

@this.Insert(index, item);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

60 changes: 60 additions & 0 deletions com.stansassets.build/BuildPipeline/Common/ReflectionUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace StansAssets.Build.Pipeline
{
//TODO: move certain methods to the com.stansassets.foundation package
public static class ReflectionUtils
{
static readonly string[] s_BuiltInAssemblyPrefixes = { "Mono.", "Unity.", "UnityEngine", "UnityEditor", "System", "mscorlib" };

public static IEnumerable<Type> FindImplementationsOf<T>(bool ignoreBuiltIn = false)
{
var baseType = typeof(T);
return FindImplementationsOf(baseType, ignoreBuiltIn);
}

public static IEnumerable<Type> FindImplementationsOf(Type baseType, bool ignoreBuiltIn = false)
{
var assemblies = GetAssembles(ignoreBuiltIn);

return assemblies
.SelectMany(assembly => assembly.GetTypes())
.Where(type => baseType.IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract);
}

public static IEnumerable<MethodInfo> FindMethodsWithAttributes<T>(bool ignoreBuiltIn = false)
{
var assemblies = GetAssembles(ignoreBuiltIn);

return assemblies
.SelectMany(assembly => assembly.GetTypes())
.SelectMany(type => type.GetMethods())
.Where(methodInfo => methodInfo.GetCustomAttributes(typeof(T), false).Length > 0);

}

public static bool HasDefaultConstructor(Type type)
{
return type.GetConstructors().Any(constructor => !constructor.GetParameters().Any());
}

static IEnumerable<Assembly> GetAssembles(bool ignoreBuiltIn = false)
{
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies();

if (ignoreBuiltIn)
{
assemblies = assemblies.Where(assembly => {
var assemblyName = assembly.GetName().Name;
return !s_BuiltInAssemblyPrefixes.Any(prefix => assemblyName.StartsWith(prefix));
});
}

return assemblies;
}

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 21 additions & 20 deletions com.stansassets.build/BuildPipeline/Core/BuildProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
using System;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.Callbacks;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace StansAssets.Build.Pipeline
{
class BuildProcessor : IPreprocessBuildWithReport
class BuildProcessor : IPreprocessBuildWithReport, IProcessSceneWithReport, IPostprocessBuildWithReport
{
const int k_CallbackOrder = 0;

static IBuildTasksContainer s_BuildTasks;
static IBuildContext s_BuildContext;

public int callbackOrder => 0;
public int callbackOrder => k_CallbackOrder;

public void OnPreprocessBuild(BuildReport report)
{
Expand All @@ -24,15 +25,29 @@ public void OnPreprocessBuild(BuildReport report)
}
}

[PostProcessBuild(0)]
public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
public void OnProcessScene(Scene scene, BuildReport report)
{
if (Application.isPlaying)
return;

var postProcessSceneTasks = s_BuildTasks.ScenePostProcessTasks;
if (postProcessSceneTasks.Count == 0)
return;

var sceneTasksRunner = new ScenePostProcessTasksRunner();
sceneTasksRunner.Run(s_BuildContext, scene, postProcessSceneTasks);
}

public void OnPostprocessBuild(BuildReport report)
{
foreach (var task in s_BuildTasks.PostBuildTasks)
{
RunBuildTask(s_BuildContext, task);
}
}

public static int GetCallbackOrder() => k_CallbackOrder;

static void RunBuildTask(IBuildContext buildContext, IBuildTask task)
{
switch (task)
Expand All @@ -48,20 +63,6 @@ static void RunBuildTask(IBuildContext buildContext, IBuildTask task)
}
}

[PostProcessScene(0)]
public static void OnPostProcessScene()
{
if (Application.isPlaying)
return;

var postProcessSceneTasks = s_BuildTasks.ScenePostProcessTasks;
if (postProcessSceneTasks.Count == 0)
return;

var sceneTasksRunner = new ScenePostProcessTasksRunner();
sceneTasksRunner.Run(s_BuildContext, postProcessSceneTasks);
}

public static IBuildTasksContainer GenerateBuildTasksContainer()
{
var tasksProvider = CreateBuildTasksProvider();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using StansAssets.Foundation;
using System;
using UnityEngine;

namespace StansAssets.Build.Pipeline
{
Expand All @@ -8,10 +9,25 @@ class DefaultBuildTasksProvider : IBuildTasksProvider
public IBuildTasksContainer GetBuildTasks(IUserEditorBuildSettings buildSettings)
{
var tasksContainer = new BuildTasksContainer();

CollectBuildTasks(tasksContainer);
CollectScenePostProcessTasks(tasksContainer);

return tasksContainer;
}

/// <summary>
/// Collects 'Pre' and 'Post' build tasks of type <see cref="IBuildTask"/>
/// </summary>
static void CollectBuildTasks(BuildTasksContainer tasksContainer)
{
var buildTasks = ReflectionUtility.FindImplementationsOf<IBuildTask>();

foreach (var taskType in buildTasks)
{
//TODO check if type has empty constructor and throw appropriate exception if it's not
if (!HasDefaultConstructor(taskType))
continue;

var task = Activator.CreateInstance(taskType) as IBuildTask;
switch (task)
{
Expand All @@ -24,18 +40,33 @@ public IBuildTasksContainer GetBuildTasks(IUserEditorBuildSettings buildSettings
tasksContainer.AddPostProcessTask(task);
break;
default:
throw new InvalidOperationException($"Unknown task type: {task.GetType().FullName}");
throw new InvalidOperationException($"Unknown task type: {taskType.FullName}");
}
}
}

static void CollectScenePostProcessTasks(BuildTasksContainer tasksContainer)
{
var scenePostProcessTasks = ReflectionUtility.FindImplementationsOf<IScenePostProcessTask>();
foreach (var taskType in scenePostProcessTasks)
{
var buildTask = Activator.CreateInstance(taskType) as IScenePostProcessTask;
tasksContainer.AddScenePostProcessTask(buildTask);
if (!HasDefaultConstructor(taskType))
continue;

var buildStep = Activator.CreateInstance(taskType) as IScenePostProcessTask;
tasksContainer.AddScenePostProcessTask(buildStep);
}
}

return tasksContainer;
static bool HasDefaultConstructor(Type taskType)
{
var hasConstructor = ReflectionUtils.HasDefaultConstructor(taskType);
if (!hasConstructor)
{
Debug.LogError($"The task {taskType.FullName} has no parameterless constructor and will be ignored");
}

return hasConstructor;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ class ScenePostProcessTasksRunner
{
readonly List<Component> m_TempComponentsCollection = new List<Component>();

public void Run(IBuildContext buildContext, IReadOnlyList<IScenePostProcessTask> postProcessSceneTasks)
public void Run(IBuildContext buildContext, Scene scene, IReadOnlyList<IScenePostProcessTask> postProcessSceneTasks)
{
var currentScene = SceneManager.GetActiveScene();
var rootGameObjects = currentScene.GetRootGameObjects();
var rootGameObjects = scene.GetRootGameObjects();
var componentsMap = GetComponentsMap(rootGameObjects);

foreach (var task in postProcessSceneTasks)
{
task.OnPostprocessScene(buildContext, currentScene);
task.OnPostprocessScene(buildContext, scene);
foreach (var pair in componentsMap)
{
var gameObject = pair.Key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
namespace StansAssets.Build.Pipeline
{
/// <summary>
/// Provides build steps.
/// Provides build tasks.
/// </summary>
public interface IBuildTasksContainer
{
/// <summary>
/// Pre process build steps. Order matters.
/// Pre process build tasks. Order matters.
/// </summary>
IReadOnlyList<IBuildTask> PreBuildTasks { get; }

/// <summary>
/// Post process build steps. Order matters.
/// Post process build tasks. Order matters.
/// </summary>
IReadOnlyList<IBuildTask> PostBuildTasks { get; }

/// <summary>
/// Scene process build steps. Order matters.
/// Scene process build tasks. Order matters.
/// </summary>
IReadOnlyList<IScenePostProcessTask> ScenePostProcessTasks { get; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace StansAssets.Build.Pipeline
{
/// <summary>
/// Represents a single async build step.
/// Represents a single async build task.
/// </summary>
public interface IAsyncBuildTask : IBuildTask
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class BuildTasksContainer : IBuildTasksContainer

public BuildTasksContainer()
{

m_PreBuildTasks = new List<IBuildTask>();
m_PostBuildTasks = new List<IBuildTask>();
m_ScenePostProcessTasks = new List<IScenePostProcessTask>();
Expand Down
Loading