// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using EpicGames.Core; using Microsoft.Extensions.Logging; using UnrealBuildBase; namespace UnrealBuildTool { /// /// Exports a target as a JSON file /// [ToolMode("JsonExport", ToolModeOptions.XmlConfig | ToolModeOptions.BuildPlatforms | ToolModeOptions.SingleInstance)] class JsonExportMode : ToolMode { /// /// Execute any actions which result in code generation (eg. ISPC compilation) /// [CommandLine("-ExecCodeGenActions")] public bool bExecCodeGenActions = false; /// /// Execute this command /// /// Command line arguments /// Exit code (always zero) /// public override async Task ExecuteAsync(CommandLineArguments Arguments, ILogger Logger) { Arguments.ApplyTo(this); // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); Arguments.ApplyTo(BuildConfiguration); List TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration, Logger); foreach (TargetDescriptor TargetDescriptor in TargetDescriptors) { // Create the target UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration, Logger); // Get the output file FileReference? OutputFile = TargetDescriptor.AdditionalArguments.GetFileReferenceOrDefault("-OutputFile=", null); if (OutputFile == null) { OutputFile = Target.ReceiptFileName.ChangeExtension(".json"); } // Execute code generation actions if (bExecCodeGenActions) { using (ISourceFileWorkingSet WorkingSet = new EmptySourceFileWorkingSet()) { // Create the makefile TargetMakefile Makefile = await Target.BuildAsync(BuildConfiguration, WorkingSet, TargetDescriptor, Logger); List Actions = Makefile.Actions.ConvertAll(x => new LinkedAction(x, TargetDescriptor)); ActionGraph.Link(Actions, Logger); // Filter all the actions to execute HashSet PrerequisiteItems = new HashSet(Makefile.Actions.SelectMany(x => x.ProducedItems).Where(x => x.HasExtension(".h") || x.HasExtension(".cpp"))); List PrerequisiteActions = ActionGraph.GatherPrerequisiteActions(Actions, PrerequisiteItems); // Execute these actions if (PrerequisiteActions.Count > 0) { Logger.LogInformation("Executing actions that produce source files..."); ActionGraph.CreateDirectoriesForProducedItems(PrerequisiteActions); await ActionGraph.ExecuteActionsAsync(BuildConfiguration, PrerequisiteActions, new List { TargetDescriptor }, Logger); } } } // Write the output file Logger.LogInformation("Writing {OutputFile}...", OutputFile); Target.ExportJson(OutputFile); } return 0; } } }