Beispiel #1
0
        /// <summary>
        /// Write project file info in JSON file.
        /// For every combination of <c>UnrealTargetPlatform</c>, <c>UnrealTargetConfiguration</c> and <c>TargetType</c>
        /// will be generated separate JSON file.
        /// Project file will be stored:
        /// For UE4:  {UE4Root}/Engine/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// For game: {GameRoot}/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// </summary>
        /// <remarks>
        /// * <c>UnrealTargetPlatform.Win32</c> will be always ignored.
        /// * <c>TargetType.Editor</c> will be generated for current platform only and will ignore <c>UnrealTargetConfiguration.Test</c> and <c>UnrealTargetConfiguration.Shipping</c> configurations
        /// * <c>TargetType.Program</c>  will be generated for current platform only and <c>UnrealTargetConfiguration.Development</c> configuration only
        /// </remarks>
        /// <param name="InPlatforms"></param>
        /// <param name="InConfigurations"></param>
        /// <param name="PlatformProjectGenerators"></param>
        /// <returns></returns>
        public override bool WriteProjectFile(List <UnrealTargetPlatform> InPlatforms,
                                              List <UnrealTargetConfiguration> InConfigurations,
                                              PlatformProjectGeneratorCollection PlatformProjectGenerators)
        {
            string             ProjectName       = ProjectFilePath.GetFileNameWithoutAnyExtensions();
            DirectoryReference projectRootFolder = DirectoryReference.Combine(RootPath, ".Rider");
            List <Tuple <FileReference, UEBuildTarget> > fileToTarget = new List <Tuple <FileReference, UEBuildTarget> >();

            foreach (UnrealTargetPlatform Platform in InPlatforms.Where(it => it != UnrealTargetPlatform.Win32))
            {
                foreach (UnrealTargetConfiguration Configuration in InConfigurations)
                {
                    foreach (ProjectTarget ProjectTarget in ProjectTargets)
                    {
                        if (TargetTypes.Any() && !TargetTypes.Contains(ProjectTarget.TargetRules.Type))
                        {
                            continue;
                        }

                        // Skip Programs for all configs except for current platform + Development configuration
                        if (ProjectTarget.TargetRules.Type == TargetType.Program && (BuildHostPlatform.Current.Platform != Platform || Configuration != UnrealTargetConfiguration.Development))
                        {
                            continue;
                        }

                        // Skip Editor for all platforms except for current platform
                        if (ProjectTarget.TargetRules.Type == TargetType.Editor && (BuildHostPlatform.Current.Platform != Platform || (Configuration == UnrealTargetConfiguration.Test || Configuration == UnrealTargetConfiguration.Shipping)))
                        {
                            continue;
                        }

                        DirectoryReference ConfigurationFolder = DirectoryReference.Combine(projectRootFolder, Platform.ToString(), Configuration.ToString());

                        DirectoryReference TargetFolder =
                            DirectoryReference.Combine(ConfigurationFolder, ProjectTarget.TargetRules.Type.ToString());

                        string DefaultArchitecture = UEBuildPlatform
                                                     .GetBuildPlatform(BuildHostPlatform.Current.Platform)
                                                     .GetDefaultArchitecture(ProjectTarget.UnrealProjectFilePath);
                        TargetDescriptor TargetDesc = new TargetDescriptor(ProjectTarget.UnrealProjectFilePath, ProjectTarget.Name,
                                                                           BuildHostPlatform.Current.Platform, UnrealTargetConfiguration.Development,
                                                                           DefaultArchitecture, Arguments);
                        UEBuildTarget BuildTarget = UEBuildTarget.Create(TargetDesc, false, false);
                        FileReference OutputFile  = FileReference.Combine(TargetFolder, $"{ProjectName}.json");
                        fileToTarget.Add(Tuple.Create(OutputFile, BuildTarget));
                    }
                }
            }
            foreach (Tuple <FileReference, UEBuildTarget> tuple in fileToTarget)
            {
                SerializeTarget(tuple.Item1, tuple.Item2);
            }

            return(true);
        }
        /// <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);
        }
        /// <summary>
        /// Execute this command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code (always zero)</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            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");
                }

                // Write the output file
                Log.TraceInformation("Writing {0}...", OutputFile);
                Target.ExportJson(OutputFile);
            }
            return(0);
        }
Beispiel #4
0
        /// <summary>
        /// Creates the makefile for a target. If an existing, valid makefile already exists on disk, loads that instead.
        /// </summary>
        /// <param name="BuildConfiguration">The build configuration</param>
        /// <param name="TargetDescriptor">Target being built</param>
        /// <param name="WorkingSet">Set of source files which are part of the working set</param>
        /// <returns>Makefile for the given target</returns>
        static TargetMakefile CreateMakefile(BuildConfiguration BuildConfiguration, TargetDescriptor TargetDescriptor, ISourceFileWorkingSet WorkingSet)
        {
            // Get the path to the makefile for this target
            FileReference MakefileLocation = null;

            if (BuildConfiguration.bUseUBTMakefiles && TargetDescriptor.SpecificFilesToCompile.Count == 0)
            {
                MakefileLocation = TargetMakefile.GetLocation(TargetDescriptor.ProjectFile, TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Architecture, TargetDescriptor.Configuration);
            }

            // Try to load an existing makefile
            TargetMakefile Makefile = null;

            if (MakefileLocation != null)
            {
                using (Timeline.ScopeEvent("TargetMakefile.Load()"))
                {
                    string ReasonNotLoaded;
                    Makefile = TargetMakefile.Load(MakefileLocation, TargetDescriptor.ProjectFile, TargetDescriptor.Platform, TargetDescriptor.AdditionalArguments.GetRawArray(), out ReasonNotLoaded);
                    if (Makefile == null)
                    {
                        Log.TraceInformation("Creating makefile for {0} ({1})", TargetDescriptor.Name, ReasonNotLoaded);
                    }
                }
            }

            // If we have a makefile, execute the pre-build steps and check it's still valid
            bool bHasRunPreBuildScripts = false;

            if (Makefile != null)
            {
                // Execute the scripts. We have to invalidate all cached file info after doing so, because we don't know what may have changed.
                if (Makefile.PreBuildScripts.Length > 0)
                {
                    Utils.ExecuteCustomBuildSteps(Makefile.PreBuildScripts);
                    DirectoryItem.ResetAllCachedInfo_SLOW();
                }

                // Don't run the pre-build steps again, even if we invalidate the makefile.
                bHasRunPreBuildScripts = true;

                // Check that the makefile is still valid
                string Reason;
                if (!TargetMakefile.IsValidForSourceFiles(Makefile, TargetDescriptor.ProjectFile, TargetDescriptor.Platform, WorkingSet, out Reason))
                {
                    Log.TraceInformation("Invalidating makefile for {0} ({1})", TargetDescriptor.Name, Reason);
                    Makefile = null;
                }
            }

            // If we couldn't load a makefile, create a new one
            if (Makefile == null)
            {
                // Create the target
                UEBuildTarget Target;
                using (Timeline.ScopeEvent("UEBuildTarget.Create()"))
                {
                    Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration.bSkipRulesCompile, BuildConfiguration.bUsePrecompiled);
                }

                // Create the pre-build scripts
                FileReference[] PreBuildScripts = Target.CreatePreBuildScripts();

                // Execute the pre-build scripts
                if (!bHasRunPreBuildScripts)
                {
                    Utils.ExecuteCustomBuildSteps(PreBuildScripts);
                    bHasRunPreBuildScripts = true;
                }

                // Build the target
                using (Timeline.ScopeEvent("UEBuildTarget.Build()"))
                {
                    const bool bIsAssemblingBuild = true;
                    Makefile = Target.Build(BuildConfiguration, WorkingSet, bIsAssemblingBuild, TargetDescriptor.SpecificFilesToCompile);
                }

                // Save the pre-build scripts onto the makefile
                Makefile.PreBuildScripts = PreBuildScripts;

                // Save the additional command line arguments
                Makefile.AdditionalArguments = TargetDescriptor.AdditionalArguments.GetRawArray();

                // Save the environment variables
                foreach (System.Collections.DictionaryEntry EnvironmentVariable in Environment.GetEnvironmentVariables())
                {
                    Makefile.EnvironmentVariables.Add(Tuple.Create((string)EnvironmentVariable.Key, (string)EnvironmentVariable.Value));
                }

                // Save the makefile for next time
                if (MakefileLocation != null)
                {
                    using (Timeline.ScopeEvent("TargetMakefile.Save()"))
                    {
                        Makefile.Save(MakefileLocation);
                    }
                }
            }
            else
            {
                // Restore the environment variables
                foreach (Tuple <string, string> EnvironmentVariable in Makefile.EnvironmentVariables)
                {
                    Environment.SetEnvironmentVariable(EnvironmentVariable.Item1, EnvironmentVariable.Item2);
                }

                // If the target needs UHT to be run, we'll go ahead and do that now
                if (Makefile.UObjectModules.Count > 0)
                {
                    const bool bIsGatheringBuild  = false;
                    const bool bIsAssemblingBuild = true;

                    FileReference ModuleInfoFileName = FileReference.Combine(Makefile.ProjectIntermediateDirectory, TargetDescriptor.Name + ".uhtmanifest");
                    ExternalExecution.ExecuteHeaderToolIfNecessary(BuildConfiguration, TargetDescriptor.ProjectFile, TargetDescriptor.Name, Makefile.TargetType, Makefile.bHasProjectScriptPlugin, UObjectModules: Makefile.UObjectModules, ModuleInfoFileName: ModuleInfoFileName, bIsGatheringBuild: bIsGatheringBuild, bIsAssemblingBuild: bIsAssemblingBuild, WorkingSet: WorkingSet);
                }
            }
            return(Makefile);
        }
Beispiel #5
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);
        }
Beispiel #6
0
        /// <summary>
        /// Write project file info in JSON file.
        /// For every combination of <c>UnrealTargetPlatform</c>, <c>UnrealTargetConfiguration</c> and <c>TargetType</c>
        /// will be generated separate JSON file.
        /// Project file will be stored:
        /// For UE4:  {UE4Root}/Engine/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// For game: {GameRoot}/Intermediate/ProjectFiles/.Rider/{Platform}/{Configuration}/{TargetType}/{ProjectName}.json
        /// </summary>
        /// <remarks>
        /// * <c>UnrealTargetPlatform.Win32</c> will be always ignored.
        /// * <c>TargetType.Editor</c> will be generated for current platform only and will ignore <c>UnrealTargetConfiguration.Test</c> and <c>UnrealTargetConfiguration.Shipping</c> configurations
        /// * <c>TargetType.Program</c>  will be generated for current platform only and <c>UnrealTargetConfiguration.Development</c> configuration only
        /// </remarks>
        /// <param name="InPlatforms"></param>
        /// <param name="InConfigurations"></param>
        /// <param name="PlatformProjectGenerators"></param>
        /// <param name="Minimize"></param>
        /// <returns></returns>
        public bool WriteProjectFile(List <UnrealTargetPlatform> InPlatforms,
                                     List <UnrealTargetConfiguration> InConfigurations,
                                     PlatformProjectGeneratorCollection PlatformProjectGenerators, JsonWriterStyle Minimize)
        {
            string             ProjectName       = ProjectFilePath.GetFileNameWithoutAnyExtensions();
            DirectoryReference ProjectRootFolder = RootPath;
            List <Tuple <FileReference, UEBuildTarget> > FileToTarget = new List <Tuple <FileReference, UEBuildTarget> >();

            foreach (UnrealTargetPlatform Platform in InPlatforms)
            {
                foreach (UnrealTargetConfiguration Configuration in InConfigurations)
                {
                    foreach (ProjectTarget ProjectTarget in ProjectTargets)
                    {
                        if (TargetTypes.Any() && !TargetTypes.Contains(ProjectTarget.TargetRules.Type))
                        {
                            continue;
                        }

                        // Skip Programs for all configs except for current platform + Development & Debug configurations
                        if (ProjectTarget.TargetRules.Type == TargetType.Program &&
                            (BuildHostPlatform.Current.Platform != Platform ||
                             !(Configuration == UnrealTargetConfiguration.Development || Configuration == UnrealTargetConfiguration.Debug)))
                        {
                            continue;
                        }

                        // Skip Editor for all platforms except for current platform
                        if (ProjectTarget.TargetRules.Type == TargetType.Editor && (BuildHostPlatform.Current.Platform != Platform || (Configuration == UnrealTargetConfiguration.Test || Configuration == UnrealTargetConfiguration.Shipping)))
                        {
                            continue;
                        }

                        DirectoryReference ConfigurationFolder = DirectoryReference.Combine(ProjectRootFolder, Platform.ToString(), Configuration.ToString());

                        DirectoryReference TargetFolder =
                            DirectoryReference.Combine(ConfigurationFolder, ProjectTarget.TargetRules.Type.ToString());

                        string DefaultArchitecture = UEBuildPlatform
                                                     .GetBuildPlatform(Platform)
                                                     .GetDefaultArchitecture(ProjectTarget.UnrealProjectFilePath);
                        TargetDescriptor TargetDesc = new TargetDescriptor(ProjectTarget.UnrealProjectFilePath, ProjectTarget.Name,
                                                                           Platform, Configuration, DefaultArchitecture, Arguments);
                        try
                        {
                            UEBuildTarget BuildTarget = UEBuildTarget.Create(TargetDesc, false, false);

                            FileReference OutputFile = FileReference.Combine(TargetFolder, $"{ProjectName}.json");
                            FileToTarget.Add(Tuple.Create(OutputFile, BuildTarget));
                        }
                        catch (Exception Ex)
                        {
                            Log.TraceWarning("Exception while generating include data for Target:{0}, Platform: {1}, Configuration: {2}", TargetDesc.Name, Platform.ToString(), Configuration.ToString());
                            Log.TraceWarning(Ex.ToString());
                        }
                    }
                }
            }
            foreach (Tuple <FileReference, UEBuildTarget> tuple in FileToTarget)
            {
                try
                {
                    CurrentTarget = tuple.Item2;
                    CurrentTarget.PreBuildSetup();
                    SerializeTarget(tuple.Item1, CurrentTarget, Minimize);
                }
                catch (Exception Ex)
                {
                    Log.TraceWarning("Exception while generating include data for Target:{0}, Platform: {1}, Configuration: {2}", tuple.Item2.AppName, tuple.Item2.Platform.ToString(), tuple.Item2.Configuration.ToString());
                    Log.TraceWarning(Ex.ToString());
                }
            }

            return(true);
        }