// 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()
{
}
}
}