diff --git a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs index 1637524c2..99a8ab13d 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs @@ -106,6 +106,7 @@ namespace Flax.Build buildData.TargetOptions.Libraries.AddRange(moduleOptions.Libraries); buildData.TargetOptions.DelayLoadLibraries.AddRange(moduleOptions.DelayLoadLibraries); buildData.TargetOptions.ScriptingAPI.Add(moduleOptions.ScriptingAPI); + buildData.TargetOptions.ExternalModules.AddRange(moduleOptions.ExternalModules); } } } diff --git a/Source/Tools/Flax.Build/Build/EngineTarget.cs b/Source/Tools/Flax.Build/Build/EngineTarget.cs index 55cc856ea..68d1aa225 100644 --- a/Source/Tools/Flax.Build/Build/EngineTarget.cs +++ b/Source/Tools/Flax.Build/Build/EngineTarget.cs @@ -184,6 +184,7 @@ namespace Flax.Build exeBuildOptions.Libraries.AddRange(mainModuleOptions.Libraries); exeBuildOptions.DelayLoadLibraries.AddRange(mainModuleOptions.DelayLoadLibraries); exeBuildOptions.ScriptingAPI.Add(mainModuleOptions.ScriptingAPI); + exeBuildOptions.ExternalModules.AddRange(mainModuleOptions.ExternalModules); buildOptions.Toolchain.LinkFiles(graph, exeBuildOptions, outputPath); } } diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/BuildOptions.cs b/Source/Tools/Flax.Build/Build/NativeCpp/BuildOptions.cs index 69f42fe3c..6cad222ba 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/BuildOptions.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/BuildOptions.cs @@ -1,5 +1,6 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. +using System; using System.Collections.Generic; using System.IO; @@ -188,6 +189,59 @@ namespace Flax.Build.NativeCpp FileReferences = new HashSet(), }; + /// + /// The external module linking options. + /// + public struct ExternalModule : IEquatable + { + public enum Types + { + Native, + CSharp, + Custom, + } + + public string Name; + public string Path; + public Types Type; + + public ExternalModule(Types type, string path, string name = null) + { + Name = name ?? System.IO.Path.GetFileNameWithoutExtension(path); + Type = type; + Path = path; + } + + /// + public bool Equals(ExternalModule other) + { + return Name == other.Name; + } + + /// + public override bool Equals(object obj) + { + return obj is ExternalModule other && Equals(other); + } + + /// + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + public override string ToString() + { + return Name; + } + } + + /// + /// The custom external binary modules to referenced by this module. Can be used to extern the custom C# or C++ library with scripts to be used at runtime. + /// + public HashSet ExternalModules = new HashSet(); + /// /// Merges the files from input source paths into source files and clears the source paths list. /// diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index a068db298..e90a088ea 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -75,6 +75,56 @@ namespace Flax.Build public BuildTargetBinaryModuleInfo[] BinaryModules; public BuildTargetReferenceInfo[] References; + internal void AddExternalBinaryModules(ref int i, string projectPath, HashSet externalModules) + { + foreach (var externalModule in externalModules) + { + var binaryModuleInfo = new BuildTargetBinaryModuleInfo + { + NativePath = string.Empty, + ManagedPath = string.Empty, + Name = externalModule.Name, + }; + + switch (externalModule.Type) + { + case BuildOptions.ExternalModule.Types.Native: + binaryModuleInfo.NativePath = externalModule.Path; + binaryModuleInfo.NativePathProcessed = ProcessPath(binaryModuleInfo.NativePath, projectPath); + break; + case BuildOptions.ExternalModule.Types.CSharp: + binaryModuleInfo.ManagedPath = externalModule.Path; + binaryModuleInfo.ManagedPathProcessed = ProcessPath(binaryModuleInfo.ManagedPath, projectPath); + break; + } + + binaryModuleInfo.NativePathProcessed = ProcessPath(binaryModuleInfo.NativePath, projectPath); + binaryModuleInfo.ManagedPathProcessed = ProcessPath(binaryModuleInfo.ManagedPath, projectPath); + + BinaryModules[i++] = binaryModuleInfo; + } + } + + internal void AddReferencedBuilds(ref int i, string projectPath, Dictionary referencedBuilds) + { + foreach (var referenceBuild in referencedBuilds) + { + var reference = referenceBuild.Value; + var referenceOutputTargetFilePath = reference.Target.GetOutputFilePath(reference.TargetOptions); + var referenceOutputPath = Path.GetDirectoryName(referenceOutputTargetFilePath); + var referenceInfo = new BuildTargetReferenceInfo + { + ProjectPath = reference.Project.ProjectPath, + Path = Path.Combine(referenceOutputPath, reference.Target.Name + ".Build.json"), + }; + + referenceInfo.ProjectPathProcessed = ProcessPath(referenceInfo.ProjectPath, projectPath); + referenceInfo.PathProcessed = ProcessPath(referenceInfo.Path, projectPath); + + References[i++] = referenceInfo; + } + } + public static string ProcessPath(string path, string projectPath) { if (string.IsNullOrEmpty(path)) @@ -319,6 +369,7 @@ namespace Flax.Build moduleOptions.Libraries.AddRange(dependencyOptions.Libraries); moduleOptions.DelayLoadLibraries.AddRange(dependencyOptions.DelayLoadLibraries); moduleOptions.ScriptingAPI.Add(dependencyOptions.ScriptingAPI); + moduleOptions.ExternalModules.AddRange(dependencyOptions.ExternalModules); } } foreach (var moduleName in moduleOptions.PublicDependencies) @@ -337,6 +388,7 @@ namespace Flax.Build moduleOptions.Libraries.AddRange(dependencyOptions.Libraries); moduleOptions.DelayLoadLibraries.AddRange(dependencyOptions.DelayLoadLibraries); moduleOptions.ScriptingAPI.Add(dependencyOptions.ScriptingAPI); + moduleOptions.ExternalModules.AddRange(dependencyOptions.ExternalModules); } } @@ -449,6 +501,7 @@ namespace Flax.Build if (dependencyModule != null && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) { moduleOptions.ScriptingAPI.Add(dependencyOptions.ScriptingAPI); + moduleOptions.ExternalModules.AddRange(dependencyOptions.ExternalModules); } } foreach (var moduleName in moduleOptions.PublicDependencies) @@ -457,6 +510,7 @@ namespace Flax.Build if (dependencyModule != null && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) { moduleOptions.ScriptingAPI.Add(dependencyOptions.ScriptingAPI); + moduleOptions.ExternalModules.AddRange(dependencyOptions.ExternalModules); } } @@ -810,6 +864,7 @@ namespace Flax.Build buildData.TargetOptions.Libraries.AddRange(moduleOptions.Libraries); buildData.TargetOptions.DelayLoadLibraries.AddRange(moduleOptions.DelayLoadLibraries); buildData.TargetOptions.ScriptingAPI.Add(moduleOptions.ScriptingAPI); + buildData.TargetOptions.ExternalModules.AddRange(moduleOptions.ExternalModules); } } } @@ -840,11 +895,13 @@ namespace Flax.Build Architecture = toolchain.Architecture.ToString(), Configuration = configuration.ToString(), HotReloadPostfix = targetBuildOptions.HotReloadPostfix, - BinaryModules = new BuildTargetBinaryModuleInfo[buildData.BinaryModules.Length], + BinaryModules = new BuildTargetBinaryModuleInfo[buildData.BinaryModules.Length + targetBuildOptions.ExternalModules.Count], References = new BuildTargetReferenceInfo[buildData.ReferenceBuilds.Count], }; int i; - for (i = 0; i < buildData.BuildInfo.BinaryModules.Length; i++) + + // Binary modules + for (i = 0; i < buildData.BinaryModules.Length; i++) { var binaryModule = buildData.BinaryModules[i]; var binaryModuleInfo = new BuildTargetBinaryModuleInfo @@ -905,23 +962,11 @@ namespace Flax.Build buildData.BuildInfo.BinaryModules[i] = binaryModuleInfo; } + + buildData.BuildInfo.AddExternalBinaryModules(ref i, project.ProjectFolderPath, targetBuildOptions.ExternalModules); i = 0; - foreach (var referenceBuild in buildData.ReferenceBuilds) - { - var reference = referenceBuild.Value; - var referenceOutputTargetFilePath = reference.Target.GetOutputFilePath(reference.TargetOptions); - var referenceOutputPath = Path.GetDirectoryName(referenceOutputTargetFilePath); - var referenceInfo = new BuildTargetReferenceInfo - { - ProjectPath = reference.Project.ProjectPath, - Path = Path.Combine(referenceOutputPath, reference.Target.Name + ".Build.json"), - }; + buildData.BuildInfo.AddReferencedBuilds(ref i, project.ProjectFolderPath, buildData.ReferenceBuilds); - referenceInfo.ProjectPathProcessed = BuildTargetInfo.ProcessPath(referenceInfo.ProjectPath, project.ProjectFolderPath); - referenceInfo.PathProcessed = BuildTargetInfo.ProcessPath(referenceInfo.Path, project.ProjectFolderPath); - - buildData.BuildInfo.References[i++] = referenceInfo; - } if (!buildData.Target.IsPreBuilt) Utilities.WriteFileIfChanged(Path.Combine(outputPath, target.Name + ".Build.json"), JsonConvert.SerializeObject(buildData.BuildInfo, Formatting.Indented)); } @@ -1071,6 +1116,7 @@ namespace Flax.Build // Merge module into target environment buildData.TargetOptions.ScriptingAPI.Add(moduleOptions.ScriptingAPI); + buildData.TargetOptions.ExternalModules.AddRange(moduleOptions.ExternalModules); foreach (var e in moduleOptions.DependencyFiles) buildData.TargetOptions.DependencyFiles.Add(e); foreach (var e in moduleOptions.OptionalDependencyFiles) @@ -1097,10 +1143,12 @@ namespace Flax.Build Architecture = architecture.ToString(), Configuration = configuration.ToString(), HotReloadPostfix = targetBuildOptions.HotReloadPostfix, - BinaryModules = new BuildTargetBinaryModuleInfo[buildData.BinaryModules.Length], + BinaryModules = new BuildTargetBinaryModuleInfo[buildData.BinaryModules.Length + targetBuildOptions.ExternalModules.Count], References = new BuildTargetReferenceInfo[buildData.ReferenceBuilds.Count], }; int i; + + // Binary modules for (i = 0; i < buildData.BuildInfo.BinaryModules.Length; i++) { var binaryModule = buildData.BinaryModules[i]; @@ -1115,23 +1163,11 @@ namespace Flax.Build buildData.BuildInfo.BinaryModules[i] = binaryModuleInfo; } + + buildData.BuildInfo.AddExternalBinaryModules(ref i, project.ProjectFolderPath, targetBuildOptions.ExternalModules); i = 0; - foreach (var referenceBuild in buildData.ReferenceBuilds) - { - var reference = referenceBuild.Value; - var referenceOutputTargetFilePath = reference.Target.GetOutputFilePath(reference.TargetOptions); - var referenceOutputPath = Path.GetDirectoryName(referenceOutputTargetFilePath); - var referenceInfo = new BuildTargetReferenceInfo - { - ProjectPath = reference.Project.ProjectPath, - Path = Path.Combine(referenceOutputPath, reference.Target.Name + ".Build.json"), - }; + buildData.BuildInfo.AddReferencedBuilds(ref i, project.ProjectFolderPath, buildData.ReferenceBuilds); - referenceInfo.ProjectPathProcessed = BuildTargetInfo.ProcessPath(referenceInfo.ProjectPath, project.ProjectFolderPath); - referenceInfo.PathProcessed = BuildTargetInfo.ProcessPath(referenceInfo.Path, project.ProjectFolderPath); - - buildData.BuildInfo.References[i++] = referenceInfo; - } if (!buildData.Target.IsPreBuilt) Utilities.WriteFileIfChanged(Path.Combine(outputPath, target.Name + ".Build.json"), JsonConvert.SerializeObject(buildData.BuildInfo, Formatting.Indented)); }