Optimize build tool
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Flax.Build.NativeCpp;
|
||||
using BuildData = Flax.Build.Builder.BuildData;
|
||||
|
||||
@@ -58,11 +57,8 @@ namespace Flax.Build.Bindings
|
||||
|
||||
private static ModuleInfo ParseModuleInner(BuildData buildData, Module module, BuildOptions moduleOptions = null)
|
||||
{
|
||||
if (buildData.ModulesInfo.TryGetValue(module, out var moduleInfo))
|
||||
return moduleInfo;
|
||||
|
||||
// Setup bindings module info descriptor
|
||||
moduleInfo = new ModuleInfo
|
||||
var moduleInfo = new ModuleInfo
|
||||
{
|
||||
Module = module,
|
||||
Name = module.BinaryModuleName,
|
||||
@@ -81,26 +77,35 @@ namespace Flax.Build.Bindings
|
||||
throw new Exception($"Cannot parse module {module.Name} without options.");
|
||||
|
||||
// Collect all header files that can have public symbols for API
|
||||
var headerFiles = moduleOptions.SourceFiles.Where(x => x.EndsWith(".h")).ToList();
|
||||
|
||||
// Skip if no header files to process
|
||||
var headerFiles = new List<string>(moduleOptions.SourceFiles.Count / 2);
|
||||
for (int i = 0; i < moduleOptions.SourceFiles.Count; i++)
|
||||
{
|
||||
if (moduleOptions.SourceFiles[i].EndsWith(".h", StringComparison.OrdinalIgnoreCase))
|
||||
headerFiles.Add(moduleOptions.SourceFiles[i]);
|
||||
}
|
||||
if (headerFiles.Count == 0)
|
||||
return moduleInfo;
|
||||
if (module.Name == "Core")
|
||||
{
|
||||
// Special case for Core module to ignore API tags defines
|
||||
for (int i = 0; i < headerFiles.Count; i++)
|
||||
{
|
||||
if (headerFiles[i].EndsWith("Config.h", StringComparison.Ordinal))
|
||||
{
|
||||
headerFiles.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use aynsc tasks or thread pool to load and parse multiple header files at once using multi-threading
|
||||
// TODO: use async tasks or thread pool to load and parse multiple header files at once using multi-threading
|
||||
|
||||
// Find and load files with API tags
|
||||
string[] headerFilesContents = null;
|
||||
//using (new ProfileEventScope("LoadHeaderFiles"))
|
||||
using (new ProfileEventScope("LoadHeaderFiles"))
|
||||
{
|
||||
var anyApi = false;
|
||||
for (int i = 0; i < headerFiles.Count; i++)
|
||||
{
|
||||
// Skip scripting tags definitions file
|
||||
if (headerFiles[i].Replace('\\', '/').EndsWith("Engine/Core/Config.h", StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
// Check if file contains any valid API tag
|
||||
var contents = File.ReadAllText(headerFiles[i]);
|
||||
for (int j = 0; j < ApiTokens.SearchTags.Length; j++)
|
||||
{
|
||||
@@ -109,15 +114,13 @@ namespace Flax.Build.Bindings
|
||||
if (headerFilesContents == null)
|
||||
headerFilesContents = new string[headerFiles.Count];
|
||||
headerFilesContents[i] = contents;
|
||||
anyApi = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyApi)
|
||||
return moduleInfo;
|
||||
}
|
||||
if (headerFilesContents == null)
|
||||
return moduleInfo;
|
||||
|
||||
// Skip if none of the headers was modified after last time generated C++ file was edited
|
||||
// TODO: skip parsing if module has API cache file -> then load it from disk
|
||||
|
||||
@@ -12,12 +12,31 @@ namespace Flax.Build
|
||||
partial class Builder
|
||||
{
|
||||
private static RulesAssembly _rules;
|
||||
private static Type[] _buildTypes;
|
||||
|
||||
/// <summary>
|
||||
/// The build configuration files postfix.
|
||||
/// </summary>
|
||||
public static string BuildFilesPostfix = ".Build.cs";
|
||||
|
||||
/// <summary>
|
||||
/// The cached list of types from Flax.Build assembly. Reused by other build tool utilities to improve performance.
|
||||
/// </summary>
|
||||
internal static Type[] BuildTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_buildTypes == null)
|
||||
{
|
||||
using (new ProfileEventScope("CacheBuildTypes"))
|
||||
{
|
||||
_buildTypes = typeof(Program).Assembly.GetTypes();
|
||||
}
|
||||
}
|
||||
return _buildTypes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The rules assembly data.
|
||||
/// </summary>
|
||||
@@ -128,7 +147,7 @@ namespace Flax.Build
|
||||
|
||||
using (new ProfileEventScope("InitInBuildPlugins"))
|
||||
{
|
||||
foreach (var type in typeof(Program).Assembly.GetTypes().Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Plugin))))
|
||||
foreach (var type in BuildTypes.Where(x => x.IsClass && !x.IsAbstract && x.IsSubclassOf(typeof(Plugin))))
|
||||
{
|
||||
var plugin = (Plugin)Activator.CreateInstance(type);
|
||||
plugin.Init();
|
||||
@@ -176,67 +195,74 @@ namespace Flax.Build
|
||||
|
||||
// Prepare targets and modules objects
|
||||
Type[] types;
|
||||
Target[] targetObjects;
|
||||
Module[] moduleObjects;
|
||||
Plugin[] pluginObjects;
|
||||
var targetObjects = new List<Target>(16);
|
||||
var moduleObjects = new List<Module>(256);
|
||||
var pluginObjects = new List<Plugin>();
|
||||
using (new ProfileEventScope("GetTypes"))
|
||||
{
|
||||
types = assembly.GetTypes();
|
||||
targetObjects = types.Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Target))).Select(type =>
|
||||
for (var i = 0; i < types.Length; i++)
|
||||
{
|
||||
var target = (Target)Activator.CreateInstance(type);
|
||||
|
||||
var targetFilename = target.Name + BuildFilesPostfix;
|
||||
target.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), targetFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (target.FilePath == null)
|
||||
var type = types[i];
|
||||
if (!type.IsClass || type.IsAbstract)
|
||||
continue;
|
||||
if (type.IsSubclassOf(typeof(Target)))
|
||||
{
|
||||
targetFilename = target.Name + "Target" + BuildFilesPostfix;
|
||||
var target = (Target)Activator.CreateInstance(type);
|
||||
|
||||
var targetFilename = target.Name + BuildFilesPostfix;
|
||||
target.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), targetFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (target.FilePath == null)
|
||||
{
|
||||
if (target.Name.EndsWith("Target"))
|
||||
{
|
||||
targetFilename = target.Name.Substring(0, target.Name.Length - "Target".Length) + BuildFilesPostfix;
|
||||
target.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), targetFilename, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
targetFilename = target.Name + "Target" + BuildFilesPostfix;
|
||||
target.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), targetFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (target.FilePath == null)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to find source file path for {0}", target));
|
||||
if (target.Name.EndsWith("Target"))
|
||||
{
|
||||
targetFilename = target.Name.Substring(0, target.Name.Length - "Target".Length) + BuildFilesPostfix;
|
||||
target.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), targetFilename, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
if (target.FilePath == null)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to find source file path for {0}", target));
|
||||
}
|
||||
}
|
||||
}
|
||||
target.FolderPath = Path.GetDirectoryName(target.FilePath);
|
||||
target.Init();
|
||||
targetObjects.Add(target);
|
||||
}
|
||||
target.FolderPath = Path.GetDirectoryName(target.FilePath);
|
||||
target.Init();
|
||||
return target;
|
||||
}).ToArray();
|
||||
moduleObjects = types.Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Module))).Select(type =>
|
||||
{
|
||||
var module = (Module)Activator.CreateInstance(type);
|
||||
|
||||
var moduleFilename = module.Name + BuildFilesPostfix;
|
||||
module.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), moduleFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (module.FilePath == null)
|
||||
else if (type.IsSubclassOf(typeof(Module)))
|
||||
{
|
||||
moduleFilename = module.Name + "Module" + BuildFilesPostfix;
|
||||
var module = (Module)Activator.CreateInstance(type);
|
||||
|
||||
var moduleFilename = module.Name + BuildFilesPostfix;
|
||||
module.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), moduleFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (module.FilePath == null)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to find source file path for {0}", module));
|
||||
moduleFilename = module.Name + "Module" + BuildFilesPostfix;
|
||||
module.FilePath = files.FirstOrDefault(path => string.Equals(Path.GetFileName(path), moduleFilename, StringComparison.OrdinalIgnoreCase));
|
||||
if (module.FilePath == null)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to find source file path for {0}", module));
|
||||
}
|
||||
}
|
||||
module.FolderPath = Path.GetDirectoryName(module.FilePath);
|
||||
module.Init();
|
||||
moduleObjects.Add(module);
|
||||
}
|
||||
module.FolderPath = Path.GetDirectoryName(module.FilePath);
|
||||
module.Init();
|
||||
return module;
|
||||
}).ToArray();
|
||||
pluginObjects = types.Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Plugin))).Select(type =>
|
||||
{
|
||||
var plugin = (Plugin)Activator.CreateInstance(type);
|
||||
plugin.Init();
|
||||
return plugin;
|
||||
}).ToArray();
|
||||
else if (type.IsSubclassOf(typeof(Plugin)))
|
||||
{
|
||||
var plugin = (Plugin)Activator.CreateInstance(type);
|
||||
|
||||
plugin.Init();
|
||||
pluginObjects.Add(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_rules = new RulesAssembly(assembly, targetObjects, moduleObjects, pluginObjects);
|
||||
_rules = new RulesAssembly(assembly, targetObjects.ToArray(), moduleObjects.ToArray(), pluginObjects.ToArray());
|
||||
}
|
||||
|
||||
return _rules;
|
||||
|
||||
@@ -330,7 +330,12 @@ namespace Flax.Build
|
||||
}
|
||||
|
||||
// Collect all files to compile
|
||||
var cppFiles = moduleOptions.SourceFiles.Where(x => x.EndsWith(".cpp")).ToList();
|
||||
var cppFiles = new List<string>(moduleOptions.SourceFiles.Count / 2);
|
||||
for (int i = 0; i < moduleOptions.SourceFiles.Count; i++)
|
||||
{
|
||||
if (moduleOptions.SourceFiles[i].EndsWith(".cpp", StringComparison.OrdinalIgnoreCase))
|
||||
cppFiles.Add(moduleOptions.SourceFiles[i]);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(module.BinaryModuleName))
|
||||
{
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace Flax.Build
|
||||
if (_platforms == null)
|
||||
{
|
||||
using (new ProfileEventScope("GetPlatforms"))
|
||||
_platforms = typeof(Platform).Assembly.GetTypes().Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Platform))).Select(Activator.CreateInstance).Cast<Platform>().ToArray();
|
||||
_platforms = Builder.BuildTypes.Where(x => x.IsClass && !x.IsAbstract && x.IsSubclassOf(typeof(Platform))).Select(Activator.CreateInstance).Cast<Platform>().ToArray();
|
||||
}
|
||||
|
||||
foreach (var platform in _platforms)
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Flax.Build
|
||||
using (new ProfileEventScope("GetSdks"))
|
||||
{
|
||||
_sdks = new Dictionary<string, Sdk>();
|
||||
var types = typeof(Sdk).Assembly.GetTypes().Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Sdk)));
|
||||
var types = Builder.BuildTypes.Where(x => !x.IsAbstract && x.IsSubclassOf(typeof(Sdk)));
|
||||
foreach (var type in types)
|
||||
{
|
||||
object instance = null;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Flax.Deps
|
||||
}
|
||||
|
||||
// Get all deps
|
||||
var dependencies = typeof(DepsBuilder).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(Dependency))).Select(Activator.CreateInstance).Cast<Dependency>().ToArray();
|
||||
var dependencies = Builder.BuildTypes.Where(x => x.IsSubclassOf(typeof(Dependency))).Select(Activator.CreateInstance).Cast<Dependency>().ToArray();
|
||||
if (dependencies.Length == 0)
|
||||
Log.Warning("No dependencies found!");
|
||||
for (var i = 0; i < dependencies.Length; i++)
|
||||
|
||||
Reference in New Issue
Block a user