/// <summary>
        /// Execute this command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code (always zero)</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, false, false);

            foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
            {
                // Create the target
                UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, false, false);

                // 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 build configuration object, and read the settings
                        BuildConfiguration BuildConfiguration = new BuildConfiguration();
                        XmlConfig.ApplyTo(BuildConfiguration);
                        Arguments.ApplyTo(BuildConfiguration);

                        // Create the makefile
                        const bool     bIsAssemblingBuild = true;
                        TargetMakefile Makefile           = Target.Build(BuildConfiguration, WorkingSet, bIsAssemblingBuild, TargetDescriptor.SingleFileToCompile);
                        ActionGraph.Link(Makefile.Actions);

                        // Filter all the actions to execute
                        HashSet <FileItem> PrerequisiteItems   = new HashSet <FileItem>(Makefile.Actions.SelectMany(x => x.ProducedItems).Where(x => x.HasExtension(".h") || x.HasExtension(".cpp")));
                        List <Action>      PrerequisiteActions = ActionGraph.GatherPrerequisiteActions(Makefile.Actions, PrerequisiteItems);

                        // Execute these actions
                        if (PrerequisiteActions.Count > 0)
                        {
                            Log.TraceInformation("Exeucting actions that produce source files...");
                            ActionGraph.ExecuteActions(BuildConfiguration, PrerequisiteActions);
                        }
                    }
                }

                // Write the output file
                Log.TraceInformation("Writing {0}...", OutputFile);
                Target.ExportJson(OutputFile);
            }
            return(0);
        }
Exemple #2
0
        /// <summary>
        /// Execute the command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Parse the filter argument
            FileFilter FileFilter = null;

            if (FilterRules.Count > 0)
            {
                FileFilter = new FileFilter(FileFilterType.Exclude);
                foreach (string FilterRule in FilterRules)
                {
                    FileFilter.AddRules(FilterRule.Split(';'));
                }
            }

            // Parse all the target descriptors
            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);

            // Generate the compile DB for each target
            using (ISourceFileWorkingSet WorkingSet = new EmptySourceFileWorkingSet())
            {
                // Find the compile commands for each file in the target
                Dictionary <FileReference, string> FileToCommand = new Dictionary <FileReference, string>();
                foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
                {
                    // Disable PCHs and unity builds for the target
                    TargetDescriptor.AdditionalArguments = TargetDescriptor.AdditionalArguments.Append(new string[] { "-NoPCH", "-DisableUnity" });

                    // Create a makefile for the target
                    UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration.bSkipRulesCompile, BuildConfiguration.bUsePrecompiled);

                    // Find the location of the compiler
                    VCEnvironment Environment = VCEnvironment.Create(WindowsCompiler.Clang, Target.Platform, Target.Rules.WindowsPlatform.Architecture, null, Target.Rules.WindowsPlatform.WindowsSdkVersion, null);
                    FileReference ClangPath   = FileReference.Combine(Environment.CompilerDir, "bin", "clang++.exe");

                    // Convince each module to output its generated code include path
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            Module.bAddGeneratedCodeIncludePath = true;
                        }
                    }

                    // Create all the binaries and modules
                    CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        CppCompileEnvironment BinaryCompileEnvironment = Binary.CreateBinaryCompileEnvironment(GlobalCompileEnvironment);
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            if (!Module.Rules.bUsePrecompiled)
                            {
                                UEBuildModuleCPP.InputFileCollection InputFileCollection = Module.FindInputFiles(Target.Platform, new Dictionary <DirectoryItem, FileItem[]>());

                                List <FileItem> InputFiles = new List <FileItem>();
                                InputFiles.AddRange(InputFileCollection.CPPFiles);
                                InputFiles.AddRange(InputFileCollection.CCFiles);

                                CppCompileEnvironment ModuleCompileEnvironment = Module.CreateModuleCompileEnvironment(Target.Rules, BinaryCompileEnvironment);

                                StringBuilder CommandBuilder = new StringBuilder();
                                CommandBuilder.AppendFormat("\"{0}\"", ClangPath.FullName);
                                foreach (FileItem ForceIncludeFile in ModuleCompileEnvironment.ForceIncludeFiles)
                                {
                                    CommandBuilder.AppendFormat(" -include \"{0}\"", ForceIncludeFile.FullName);
                                }
                                foreach (string Definition in ModuleCompileEnvironment.Definitions)
                                {
                                    CommandBuilder.AppendFormat(" -D\"{0}\"", Definition);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.UserIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.SystemIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }

                                foreach (FileItem InputFile in InputFiles)
                                {
                                    if (FileFilter == null || FileFilter.Matches(InputFile.Location.MakeRelativeTo(UnrealBuildTool.RootDirectory)))
                                    {
                                        FileToCommand[InputFile.Location] = String.Format("{0} \"{1}\"", CommandBuilder, InputFile.FullName);
                                    }
                                }
                            }
                        }
                    }
                }

                // Write the compile database
                FileReference DatabaseFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "compile_commands.json");
                using (JsonWriter Writer = new JsonWriter(DatabaseFile))
                {
                    Writer.WriteArrayStart();
                    foreach (KeyValuePair <FileReference, string> FileCommandPair in FileToCommand.OrderBy(x => x.Key.FullName))
                    {
                        Writer.WriteObjectStart();
                        Writer.WriteValue("file", FileCommandPair.Key.FullName);
                        Writer.WriteValue("command", FileCommandPair.Value);
                        Writer.WriteValue("directory", UnrealBuildTool.EngineSourceDirectory.ToString());
                        Writer.WriteObjectEnd();
                    }
                    Writer.WriteArrayEnd();
                }
            }

            return(0);
        }