diff --git a/Source/Editor/Editor.Build.cs b/Source/Editor/Editor.Build.cs index 4d7d33d65..3f9156b5d 100644 --- a/Source/Editor/Editor.Build.cs +++ b/Source/Editor/Editor.Build.cs @@ -37,7 +37,6 @@ public class Editor : EditorModule base.Setup(options); options.PublicDependencies.Add("Engine"); - options.PrivateDependencies.Add("Main"); options.PrivateDependencies.Add("pugixml"); options.PrivateDependencies.Add("UniversalAnalytics"); options.PrivateDependencies.Add("ContentImporters"); diff --git a/Source/FlaxGame.Build.cs b/Source/FlaxGame.Build.cs index 4604256cb..11884f458 100644 --- a/Source/FlaxGame.Build.cs +++ b/Source/FlaxGame.Build.cs @@ -51,7 +51,6 @@ public class FlaxGame : EngineTarget // Build engine as DLL to be linked in the game UWP project if (options.Platform.Target == TargetPlatform.XboxOne || options.Platform.Target == TargetPlatform.UWP) { - OutputType = TargetOutputType.Library; options.LinkEnv.Output = LinkerOutput.SharedLibrary; options.LinkEnv.GenerateWindowsMetadata = true; options.LinkEnv.GenerateDocumentation = true; diff --git a/Source/Tools/Flax.Build/Build/EngineTarget.cs b/Source/Tools/Flax.Build/Build/EngineTarget.cs index f1b71ed80..f310a4814 100644 --- a/Source/Tools/Flax.Build/Build/EngineTarget.cs +++ b/Source/Tools/Flax.Build/Build/EngineTarget.cs @@ -2,6 +2,8 @@ using System; using System.IO; +using Flax.Build.Graph; +using Flax.Build.NativeCpp; namespace Flax.Build { @@ -14,7 +16,7 @@ namespace Flax.Build private static Version _engineVersion; /// - /// Gets the engine version (from Version.h in the engine source). + /// Gets the engine version. /// public static Version EngineVersion { @@ -40,5 +42,120 @@ namespace Flax.Build Modules.Add("Main"); Modules.Add("Engine"); } + + /// + public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType) + { + // If building engine executable for platform doesn't support referencing it when linking game shared libraries + if (UseSymbolsExports && (outputType ?? OutputType) == TargetOutputType.Executable && !options.Platform.HasExecutableFileReferenceSupport) + { + // Build into shared library + outputType = TargetOutputType.Library; + } + + return base.GetOutputFilePath(options, outputType); + } + + /// + public override void SetupTargetEnvironment(BuildOptions options) + { + base.SetupTargetEnvironment(options); + + // If building engine executable for platform doesn't support referencing it when linking game shared libraries + if (UseSymbolsExports && OutputType == TargetOutputType.Executable && !options.Platform.HasExecutableFileReferenceSupport) + { + // Build into shared library + options.LinkEnv.Output = LinkerOutput.SharedLibrary; + } + } + + /// + public override void PreBuild(TaskGraph graph, BuildOptions buildOptions) + { + // If building engine executable for platform doesn't support referencing it when linking game shared libraries + if (UseSymbolsExports && OutputType == TargetOutputType.Executable && !buildOptions.Platform.HasExecutableFileReferenceSupport) + { + // Don't link Main module into shared library + Modules.Remove("Main"); + } + + base.PreBuild(graph, buildOptions); + } + + /// + public override void PostBuild(TaskGraph graph, BuildOptions buildOptions) + { + base.PostBuild(graph, buildOptions); + + // If building engine executable for platform doesn't support referencing it when linking game shared libraries + if (UseSymbolsExports && OutputType == TargetOutputType.Executable && !buildOptions.Platform.HasExecutableFileReferenceSupport) + { + // Build additional executable with Main module only that uses shared library + using (new ProfileEventScope("BuildExecutable")) + { + BuildMainExecutable(graph, buildOptions); + } + + // Restore state from PreBuild + Modules.Add("Main"); + } + } + + private void BuildMainExecutable(TaskGraph graph, BuildOptions buildOptions) + { + var outputPath = Path.Combine(buildOptions.OutputFolder, buildOptions.Platform.GetLinkOutputFileName(OutputName, LinkerOutput.Executable)); + var exeBuildOptions = Builder.GetBuildOptions(this, buildOptions.Platform, buildOptions.Toolchain, buildOptions.Architecture, buildOptions.Configuration, buildOptions.WorkingDirectory); + exeBuildOptions.LinkEnv.Output = LinkerOutput.Executable; + var rules = Builder.GenerateRulesAssembly(); + var buildData = new Builder.BuildData + { + Rules = rules, + Target = this, + Graph = graph, + TargetOptions = exeBuildOptions, + Platform = buildOptions.Platform, + Toolchain = buildOptions.Toolchain, + Architecture = buildOptions.Architecture, + Configuration = buildOptions.Configuration, + }; + + // Build Main module + var mainModule = rules.GetModule("Main"); + var mainModuleOutputPath = Path.Combine(exeBuildOptions.IntermediateFolder, mainModule.Name); + if (!IsPreBuilt && !Directory.Exists(mainModuleOutputPath)) + Directory.CreateDirectory(mainModuleOutputPath); + var mainModuleOptions = new BuildOptions + { + Target = this, + Platform = buildOptions.Platform, + Toolchain = buildOptions.Toolchain, + Architecture = buildOptions.Architecture, + Configuration = buildOptions.Configuration, + CompileEnv = (CompileEnvironment)exeBuildOptions.CompileEnv.Clone(), + LinkEnv = (LinkEnvironment)exeBuildOptions.LinkEnv.Clone(), + IntermediateFolder = mainModuleOutputPath, + OutputFolder = mainModuleOutputPath, + WorkingDirectory = exeBuildOptions.WorkingDirectory, + HotReloadPostfix = exeBuildOptions.HotReloadPostfix, + }; + mainModuleOptions.SourcePaths.Add(mainModule.FolderPath); + mainModule.Setup(mainModuleOptions); + mainModuleOptions.MergeSourcePathsIntoSourceFiles(); + mainModuleOptions.CompileEnv.PreprocessorDefinitions.Add("FLAXENGINE_API=DLLIMPORT"); + Builder.BuildModuleInner(buildData, mainModule, mainModuleOptions, false); + + // Link executable + exeBuildOptions.LinkEnv.InputLibraries.Add(Path.Combine(buildOptions.OutputFolder, buildOptions.Platform.GetLinkOutputFileName(OutputName, LinkerOutput.SharedLibrary))); + foreach (var e in mainModuleOptions.OutputFiles) + exeBuildOptions.LinkEnv.InputFiles.Add(e); + foreach (var e in mainModuleOptions.DependencyFiles) + exeBuildOptions.DependencyFiles.Add(e); + foreach (var e in mainModuleOptions.OptionalDependencyFiles) + exeBuildOptions.OptionalDependencyFiles.Add(e); + exeBuildOptions.Libraries.AddRange(mainModuleOptions.Libraries); + exeBuildOptions.DelayLoadLibraries.AddRange(mainModuleOptions.DelayLoadLibraries); + exeBuildOptions.ScriptingAPI.Add(mainModuleOptions.ScriptingAPI); + buildOptions.Toolchain.LinkFiles(graph, exeBuildOptions, outputPath); + } } } diff --git a/Source/Tools/Flax.Build/Build/GameTarget.cs b/Source/Tools/Flax.Build/Build/GameTarget.cs index 6e459da97..72aeaf2c6 100644 --- a/Source/Tools/Flax.Build/Build/GameTarget.cs +++ b/Source/Tools/Flax.Build/Build/GameTarget.cs @@ -46,7 +46,6 @@ namespace Flax.Build Architectures = new[] { TargetArchitecture.x64, - TargetArchitecture.x86, }; ConfigurationName = "Editor"; GlobalDefinitions.Add("USE_EDITOR"); diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index af50cfe1e..40a509d60 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -180,6 +180,23 @@ namespace Flax.Build /// The configuration. /// The list of modules to use for build (unique items). public static Dictionary CollectModules(RulesAssembly rules, Platform platform, Target target, BuildOptions targetBuildOptions, Toolchain toolchain, TargetArchitecture architecture, TargetConfiguration configuration) + { + return CollectModules(rules, platform, target, targetBuildOptions, toolchain, architecture, configuration, target.Modules); + } + + /// + /// Collects the modules required to build (includes dependencies). + /// + /// The rules. + /// The target. + /// The target build options. + /// The platform. + /// The toolchain. + /// The architecture. + /// The configuration. + /// The list of root modules to start collection. + /// The list of modules to use for build (unique items). + public static Dictionary CollectModules(RulesAssembly rules, Platform platform, Target target, BuildOptions targetBuildOptions, Toolchain toolchain, TargetArchitecture architecture, TargetConfiguration configuration, IEnumerable moduleNames) { var buildData = new BuildData { @@ -193,7 +210,7 @@ namespace Flax.Build }; // Collect all modules - foreach (var moduleName in target.Modules) + foreach (var moduleName in moduleNames) { var module = rules.GetModule(moduleName); if (module != null) @@ -259,7 +276,7 @@ namespace Flax.Build return moduleOptions; } - private static void BuildModuleInner(BuildData buildData, Module module, BuildOptions moduleOptions) + internal static void BuildModuleInner(BuildData buildData, Module module, BuildOptions moduleOptions, bool withApi = true) { // Inherit build environment from dependent modules foreach (var moduleName in moduleOptions.PrivateDependencies) @@ -337,7 +354,7 @@ namespace Flax.Build cppFiles.Add(moduleOptions.SourceFiles[i]); } - if (!string.IsNullOrEmpty(module.BinaryModuleName)) + if (!string.IsNullOrEmpty(module.BinaryModuleName) && withApi) { // Generate scripting bindings using (new ProfileEventScope("GenerateBindings")) @@ -396,7 +413,7 @@ namespace Flax.Build } } - private static void BuildModuleInnerBindingsOnly(BuildData buildData, Module module, BuildOptions moduleOptions) + internal static void BuildModuleInnerBindingsOnly(BuildData buildData, Module module, BuildOptions moduleOptions) { // Inherit build environment from dependent modules foreach (var moduleName in moduleOptions.PrivateDependencies) @@ -751,7 +768,9 @@ namespace Flax.Build using (new ProfileEventScope("BuildBindings")) { if (!buildData.Target.IsPreBuilt) + { BuildTargetBindings(rules, graph, buildData); + } } // Link modules into a target diff --git a/Source/Tools/Flax.Build/Build/Platform.cs b/Source/Tools/Flax.Build/Build/Platform.cs index 15addce27..79c30f969 100644 --- a/Source/Tools/Flax.Build/Build/Platform.cs +++ b/Source/Tools/Flax.Build/Build/Platform.cs @@ -66,11 +66,6 @@ namespace Flax.Build /// public abstract bool HasRequiredSDKsInstalled { get; } - /// - /// Gets a value indicating whether precompiled headers are supported on that platform. - /// - public abstract bool HasPrecompiledHeaderSupport { get; } - /// /// Gets a value indicating whether that platform supports shared libraries (dynamic link libraries). /// @@ -81,6 +76,11 @@ namespace Flax.Build /// public virtual bool HasModularBuildSupport => true; + /// + /// Gets a value indicating whether that platform supports using executable file as a reference when linking shared library. Otherwise, platform enforces monolithic linking or separate shared libraries usage. + /// + public virtual bool HasExecutableFileReferenceSupport => false; + /// /// Gets the executable file extension (including leading dot). /// @@ -102,9 +102,19 @@ namespace Flax.Build public abstract string ProgramDatabaseFileExtension { get; } /// - /// Gets the executable and library files prefix. + /// Gets the executable files prefix. /// - public virtual string BinaryFilePrefix => string.Empty; + public virtual string ExecutableFilePrefix => string.Empty; + + /// + /// Gets the shared library files prefix. + /// + public virtual string SharedLibraryFilePrefix => string.Empty; + + /// + /// Gets the statuc library files prefix. + /// + public virtual string StaticLibraryFilePrefix => string.Empty; /// /// Gets the default project format used by the given platform. @@ -138,10 +148,10 @@ namespace Flax.Build { switch (output) { - case LinkerOutput.Executable: return BinaryFilePrefix + name + ExecutableFileExtension; - case LinkerOutput.SharedLibrary: return BinaryFilePrefix + name + SharedLibraryFileExtension; + case LinkerOutput.Executable: return ExecutableFilePrefix + name + ExecutableFileExtension; + case LinkerOutput.SharedLibrary: return SharedLibraryFilePrefix + name + SharedLibraryFileExtension; case LinkerOutput.StaticLibrary: - case LinkerOutput.ImportLibrary: return BinaryFilePrefix + name + StaticLibraryFileExtension; + case LinkerOutput.ImportLibrary: return StaticLibraryFilePrefix + name + StaticLibraryFileExtension; default: throw new ArgumentOutOfRangeException(nameof(output), output, null); } } diff --git a/Source/Tools/Flax.Build/Platforms/Android/AndroidPlatform.cs b/Source/Tools/Flax.Build/Platforms/Android/AndroidPlatform.cs index bbf40f152..5bf7fff0f 100644 --- a/Source/Tools/Flax.Build/Platforms/Android/AndroidPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Android/AndroidPlatform.cs @@ -20,12 +20,15 @@ namespace Flax.Build.Platforms /// public override bool HasSharedLibrarySupport => true; + + /// + public override bool HasExecutableFileReferenceSupport => true; /// public override string ExecutableFileExtension => ".so"; /// - public override string BinaryFilePrefix => "lib"; + public override string ExecutableFilePrefix => "lib"; /// /// Initializes a new instance of the class. diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs index 3c6c8ae1b..64cd88926 100644 --- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs @@ -55,7 +55,7 @@ namespace Flax.Build.Platforms args.Add("-mssse3"); } - if (options.Target.OutputType == TargetOutputType.Library) + if (options.LinkEnv.Output == LinkerOutput.SharedLibrary) { args.Add("-fPIC"); } diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs index 9d3cedc07..b3e405859 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixPlatform.cs @@ -11,9 +11,6 @@ namespace Flax.Build.Platforms /// public abstract class UnixPlatform : Platform { - /// - public override bool HasPrecompiledHeaderSupport => false; - /// public override string ExecutableFileExtension => string.Empty; @@ -26,6 +23,12 @@ namespace Flax.Build.Platforms /// public override string ProgramDatabaseFileExtension => string.Empty; + /// + public override string SharedLibraryFilePrefix => "lib"; + + /// + public override string StaticLibraryFilePrefix => "lib"; + /// public override ProjectFormat DefaultProjectFormat => ProjectFormat.VisualStudioCode; diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs index b7ddf0605..fca112e9c 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsPlatformBase.cs @@ -122,11 +122,11 @@ namespace Flax.Build.Platforms /// public override bool HasRequiredSDKsInstalled => _hasRequiredSDKsInstalled; - /// - public override bool HasPrecompiledHeaderSupport => true; - /// public override bool HasSharedLibrarySupport => true; + + /// + public override bool HasExecutableFileReferenceSupport => true; /// public override string ExecutableFileExtension => ".exe";