// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; using System.IO; using System.Collections.Generic; using Flax.Build.Graph; using Flax.Build.NativeCpp; namespace Flax.Build { /// /// The target types. /// public enum TargetType { /// /// The C++ project. /// NativeCpp, /// /// The C# Mono project. /// DotNet, /// /// The C# .NET SDK project. /// DotNetCore, } /// /// The target output product types. /// public enum TargetOutputType { /// /// The standalone executable file. /// Executable, /// /// The library file. /// Library, } /// /// The target binaries linking types. /// public enum TargetLinkType { /// /// Link all modules (included into a build) into a single binary. /// Monolithic, /// /// Link all modules into individual dynamic libraries. /// Modular, } /// /// Defines a build target that combines modules to produce a final executable file or composite library. /// public class Target { /// /// The target name. /// public string Name; /// /// The project name. /// public string ProjectName; /// /// The target output binary name. /// public string OutputName; /// /// The target file path. /// public string FilePath; /// /// The path of the folder that contains this target file. /// public string FolderPath; /// /// True if the build target is Editor or Editor environment, otherwise false. Can be used to modify build environment when building for Editor. /// public bool IsEditor; /// /// True if target is pre built and might not contain full sources (eg. binaries are shipped with pre-build target data without sources). /// public bool IsPreBuilt = false; /// /// True if export symbols when building this target. /// public bool UseSymbolsExports = true; /// /// The target type. /// public TargetType Type = TargetType.NativeCpp; /// /// The target output type. /// public TargetOutputType OutputType = TargetOutputType.Executable; /// /// The target link type. /// public TargetLinkType LinkType = TargetLinkType.Modular; /// /// The target platforms. /// public TargetPlatform[] Platforms = Globals.AllPlatforms; /// /// The target platform architectures. /// public TargetArchitecture[] Architectures = Globals.AllArchitectures; /// /// The target build configurations. /// public TargetConfiguration[] Configurations = Globals.AllConfigurations; /// /// The custom prefix for the target configuration. Null value indicates the project name as a prefix (or gathered from CustomExternalProjectFilePath). /// public string ConfigurationName; /// /// The collection of macros to define globally across the whole target (for all of its modules). /// public List GlobalDefinitions = new List(); /// /// The collection of the modules to be compiled into the target (module names). /// public List Modules = new List(); /// /// The resource file for Win32 platforms to be included into the output executable file (can be used to customize app icon, description and file copyright note). /// public string Win32ResourceFile; /// /// the custom project file path (disables project file generation for this target). /// public string CustomExternalProjectFilePath; /// /// Initializes a new instance of the class. /// public Target() { var type = GetType(); Name = type.Name; ProjectName = Name; OutputName = Name; } /// /// Initializes the target properties. /// public virtual void Init() { GlobalDefinitions.Add("UNICODE"); GlobalDefinitions.Add("_UNICODE"); } /// /// Gets the supported architectures for the given platform. /// /// The platform. /// The target architectures collection. public virtual TargetArchitecture[] GetArchitectures(TargetPlatform platform) { return Architectures; } /// /// Selects the referenced target to build from the list of possible targets (eg. editor targets pick editor targets). /// /// The project to pick the target from. /// The targets declared within the project. /// The target to reference. public virtual Target SelectReferencedTarget(ProjectInfo project, Target[] projectTargets) { for (int i = 0; i < projectTargets.Length; i++) { if (projectTargets[i].IsEditor == IsEditor) return projectTargets[i]; } return projectTargets.Length != 0 ? projectTargets[0] : null; } /// /// Gets the output file path. /// /// The build options. /// The custom output type (for default one override). /// The output file path. public virtual string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null) { LinkerOutput linkerOutput; switch (outputType ?? OutputType) { case TargetOutputType.Executable: linkerOutput = LinkerOutput.Executable; break; case TargetOutputType.Library: linkerOutput = LinkerOutput.SharedLibrary; break; default: throw new ArgumentOutOfRangeException(); } return Path.Combine(options.OutputFolder, options.Platform.GetLinkOutputFileName(OutputName + options.HotReloadPostfix, linkerOutput)); } /// /// Setups the target building environment (native C++). Allows to modify compiler and linker options. Options applied here are used by all modules included into this target (can be overridden per module). /// /// The build options. public virtual void SetupTargetEnvironment(BuildOptions options) { options.CompileEnv.PreprocessorDefinitions.AddRange(GlobalDefinitions); options.LinkEnv.Output = OutputType == TargetOutputType.Executable ? LinkerOutput.Executable : LinkerOutput.SharedLibrary; if (!options.Platform.HasModularBuildSupport) { // Building target into single executable (forced by platform) UseSymbolsExports = false; LinkType = TargetLinkType.Monolithic; OutputType = TargetOutputType.Executable; options.LinkEnv.Output = LinkerOutput.Executable; Modules.Add("Main"); } options.CompileEnv.EnableExceptions = true; // TODO: try to disable this! switch (options.Configuration) { case TargetConfiguration.Debug: options.CompileEnv.PreprocessorDefinitions.Add("BUILD_DEBUG"); options.CompileEnv.FunctionLevelLinking = false; options.CompileEnv.Optimization = false; options.CompileEnv.FavorSizeOrSpeed = FavorSizeOrSpeed.Neither; options.CompileEnv.DebugInformation = true; options.CompileEnv.RuntimeChecks = true; options.CompileEnv.StringPooling = false; options.CompileEnv.IntrinsicFunctions = false; options.CompileEnv.BufferSecurityCheck = true; options.CompileEnv.Inlining = false; options.CompileEnv.WholeProgramOptimization = false; options.LinkEnv.DebugInformation = true; options.LinkEnv.LinkTimeCodeGeneration = false; options.LinkEnv.UseIncrementalLinking = true; options.LinkEnv.Optimization = false; break; case TargetConfiguration.Development: options.CompileEnv.PreprocessorDefinitions.Add("BUILD_DEVELOPMENT"); options.CompileEnv.FunctionLevelLinking = true; options.CompileEnv.Optimization = true; options.CompileEnv.FavorSizeOrSpeed = FavorSizeOrSpeed.FastCode; options.CompileEnv.DebugInformation = true; options.CompileEnv.RuntimeChecks = false; options.CompileEnv.StringPooling = true; options.CompileEnv.IntrinsicFunctions = true; options.CompileEnv.BufferSecurityCheck = true; options.CompileEnv.Inlining = true; options.CompileEnv.WholeProgramOptimization = false; options.LinkEnv.DebugInformation = true; options.LinkEnv.LinkTimeCodeGeneration = false; options.LinkEnv.UseIncrementalLinking = true; options.LinkEnv.Optimization = true; break; case TargetConfiguration.Release: options.CompileEnv.PreprocessorDefinitions.Add("BUILD_RELEASE"); options.CompileEnv.FunctionLevelLinking = true; options.CompileEnv.Optimization = true; options.CompileEnv.FavorSizeOrSpeed = FavorSizeOrSpeed.FastCode; options.CompileEnv.DebugInformation = false; options.CompileEnv.RuntimeChecks = false; options.CompileEnv.StringPooling = true; options.CompileEnv.IntrinsicFunctions = true; options.CompileEnv.BufferSecurityCheck = false; options.CompileEnv.Inlining = true; options.CompileEnv.WholeProgramOptimization = true; options.LinkEnv.DebugInformation = false; options.LinkEnv.LinkTimeCodeGeneration = true; options.LinkEnv.UseIncrementalLinking = false; options.LinkEnv.Optimization = true; break; default: throw new ArgumentOutOfRangeException(); } if (options.CompileEnv.UseDebugCRT) options.CompileEnv.PreprocessorDefinitions.Add("_DEBUG"); else options.CompileEnv.PreprocessorDefinitions.Add("NDEBUG"); } /// /// Called before building this target. /// public virtual void PreBuild() { } /// /// Called before building this target with a given build options. Can be used to inject custom commands into the task graph. /// /// The task graph. /// The current build options. public virtual void PreBuild(TaskGraph graph, BuildOptions buildOptions) { } /// /// Called after building this target with a given build options. Can be used to inject custom commands into the task graph. /// /// The task graph. /// The current build options. public virtual void PostBuild(TaskGraph graph, BuildOptions buildOptions) { } /// /// Called after building this target. /// public virtual void PostBuild() { } } }