public void Generate()

in Sharpmake.Generators/FastBuild/Bff.cs [208:1552]


        public void Generate(
            Builder builder,
            Project project,
            List<Project.Configuration> configurations,
            string projectFile,
            List<string> generatedFiles,
            List<string> skipFiles
        )
        {
            if (!FastBuildSettings.FastBuildSupportEnabled)
                return;

            //To make sure that all the projects are fastbuild
            configurations = configurations.Where(x => x.IsFastBuild && !x.DoNotGenerateFastBuild).OrderBy(x => x.Platform).ToList();
            if (!configurations.Any())
                return;

            Project.Configuration firstConf = configurations.First();
            string projectName = firstConf.ProjectName;
            string projectPath = new FileInfo(projectFile).Directory.FullName;
            var context = new BffGenerationContext(builder, project, projectPath, configurations);
            string projectBffFile = Bff.GetBffFileName(projectPath, firstConf.BffFileName); // TODO: bff file name could be different per conf, hence we would generate more than one file
            List<Vcxproj.ProjectFile> filesInNonDefaultSection;
            Dictionary<Project.Configuration, Dictionary<SubConfig, List<Vcxproj.ProjectFile>>> confSourceFiles;
            using (builder.CreateProfilingScope("BffGenerator.Generate:GetGeneratedFiles"))
            {
                confSourceFiles = GetGeneratedFiles(context, configurations, out filesInNonDefaultSection);
            }

            // Generate all configuration options onces...
            var options = new Dictionary<Project.Configuration, Options.ExplicitOptions>();
            var cmdLineOptions = new Dictionary<Project.Configuration, ProjectOptionsGenerator.VcxprojCmdLineOptions>();
            var dependenciesInfoPerConf = new Dictionary<Project.Configuration, DependenciesInfo>();
            ProjectOptionsGenerator projectOptionsGen;
            using (builder.CreateProfilingScope("BffGenerator.Generate:ProjectOptionsGenerator()"))
            {
                projectOptionsGen = new ProjectOptionsGenerator();
            }
            using (builder.CreateProfilingScope("BffGenerator.Generate:confs1"))
            {
                foreach (Project.Configuration conf in configurations)
                {
                    context.Options = new Options.ExplicitOptions();
                    context.CommandLineOptions = new ProjectOptionsGenerator.VcxprojCmdLineOptions();
                    context.Configuration = conf;

                    GenerateBffOptions(projectOptionsGen, context, dependenciesInfoPerConf);

                    options.Add(conf, context.Options);
                    cmdLineOptions.Add(conf, (ProjectOptionsGenerator.VcxprojCmdLineOptions)context.CommandLineOptions);

                    // Validation of unsupported cases
                    if (conf.EventPreLink.Count > 0)
                        throw new Error("Sharpmake-FastBuild : Pre-Link Events not yet supported.");
                    if (context.Options["IgnoreImportLibrary"] == "true" && conf.ExportDllSymbols)
                        throw new Error("Sharpmake-FastBuild : IgnoreImportLibrary not yet supported, set ExportDllSymbols to false for similar behavior.");

                    if (conf.Output != Project.Configuration.OutputType.None && conf.FastBuildBlobbed)
                    {
                        ConfigureUnities(context, confSourceFiles);
                    }
                }
            }
            ResolveUnities(project, projectPath);

            // Start writing Bff
            Resolver resolver = new Resolver();
            var bffGenerator = new FileGenerator(resolver);
            var bffGeneratorProject = new FileGenerator(resolver);
            var bffWholeFileGenerator = new FileGenerator(resolver);

            using (bffWholeFileGenerator.Declare("fastBuildProjectName", projectName))
            {
                bffWholeFileGenerator.Write(Template.ConfigurationFile.HeaderFile);
            }

            int configIndex = 0;

            var allFileCustomBuild = new Dictionary<string, Project.Configuration.CustomFileBuildStepData>();

            Dictionary<string, bool> confBffHasMasters = new Dictionary<string, bool>();

            var configurationsToBuild = confSourceFiles.Keys.OrderBy(x => x.Platform).ToList();
            foreach (Project.Configuration conf in configurationsToBuild)
            {
                if (!conf.Platform.IsSupportedFastBuildPlatform())
                    continue;

                var platformBff = PlatformRegistry.Get<IPlatformBff>(conf.Platform);
                var clangPlatformBff = PlatformRegistry.Query<IClangPlatformBff>(conf.Platform);
                var applePlatformBff = PlatformRegistry.Query<IApplePlatformBff>(conf.Platform);
                var microsoftPlatformBff = PlatformRegistry.Query<IMicrosoftPlatformBff>(conf.Platform);
                var dotNetConf = Util.IsDotNet(conf);

                if (conf.FastBuildMasterBffList.Any())
                    confBffHasMasters[conf.BffFullFileName] = true;
                else
                    confBffHasMasters.TryAdd(conf.BffFullFileName, false);

                // TODO: really not ideal, refactor and move the properties we need from it someplace else
                var vcxprojPlatform = PlatformRegistry.Query<IPlatformVcxproj>(conf.Platform);

                using (resolver.NewScopedParameter("conf", conf))
                {
                    if (conf.IsBlobbed && conf.FastBuildBlobbed)
                    {
                        throw new Error("Sharpmake-FastBuild: Configuration " + conf + " is configured for blobbing by fastbuild and sharpmake. This is illegal.");
                    }

                    var confSubConfigs = confSourceFiles[conf];
                    ProjectOptionsGenerator.VcxprojCmdLineOptions confCmdLineOptions = cmdLineOptions[conf];

                    // We will need as many "sub"-libraries as subConfigs to generate the final library
                    int subConfigIndex = 0;
                    Strings subConfigObjectList = new Strings();
                    bool isUnity = false;

                    if (configIndex == 0 || configurationsToBuild[configIndex - 1].Platform != conf.Platform)
                    {
                        using (bffGenerator.Declare("fastBuildDefine", GetPlatformSpecificDefine(conf.Platform)))
                            bffGenerator.Write(Template.ConfigurationFile.PlatformBeginSection);
                    }
                    List<string> resourceFilesSections = new List<string>();
                    List<string> embeddedResourceFilesSections = new List<string>();
                    List<string> additionalLibs = new List<string>();

                    Options.ExplicitOptions confOptions = options[conf];

                    bool confUseLibraryDependencyInputs = Options.GetObject<Options.Vc.Linker.UseLibraryDependencyInputs>(conf) == Options.Vc.Linker.UseLibraryDependencyInputs.Enable;
                    string outputFile = confOptions["OutputFile"];

                    bool isOutputTypeExe = conf.Output == Project.Configuration.OutputType.Exe;
                    bool isOutputTypeAppleApp = conf.Output == Project.Configuration.OutputType.AppleApp;
                    bool isOutputTypeDll = conf.Output == Project.Configuration.OutputType.Dll;
                    bool isOutputTypeLib = conf.Output == Project.Configuration.OutputType.Lib;
                    bool isOutputTypeExeOrDllOrAppleApp = isOutputTypeExe || isOutputTypeDll || isOutputTypeAppleApp;

                    var dependenciesInfo = dependenciesInfoPerConf[conf];
                    OrderableStrings additionalDependencies = dependenciesInfo.AdditionalDependencies;

                    foreach (var subConfig in confSubConfigs.Keys)
                    {
                        var scopedOptions = new List<Options.ScopedOption>();

                        bool isDefaultSubConfig = s_DefaultSubConfig.Equals(subConfig);

                        bool isUsePrecomp = subConfig.IsUsePrecomp && conf.PrecompSource != null;
                        bool isCompileAsCFile = subConfig.Languages.HasFlag(Languages.C);
                        bool isCompileAsCPPFile = subConfig.Languages.HasFlag(Languages.CPP);
                        bool isCompileAsObjCFile = subConfig.Languages.HasFlag(Languages.ObjC);
                        bool isCompileAsObjCPPFile = subConfig.Languages.HasFlag(Languages.ObjCPP);
                        bool isCompileAsSwiftFile = subConfig.Languages.HasFlag(Languages.Swift);
                        bool isASMFileSection = subConfig.Languages.HasFlag(Languages.Asm);
                        bool isNASMFileSection = subConfig.Languages.HasFlag(Languages.Nasm);
                        bool isCompileAsCLRFile = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.CLR);
                        bool isCompileAsNonCLRFile = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.NonCLR);
                        bool isConsumeWinRTExtensions = subConfig.LanguageFeatures.HasFlag(LanguageFeatures.ConsumeWinRTExtensions) || (Options.GetObject<Options.Vc.Compiler.CompileAsWinRT>(conf) == Options.Vc.Compiler.CompileAsWinRT.Enable);
                        Options.Vc.Compiler.Exceptions exceptionsSetting = subConfig.Exceptions;

                        bool isFirstSubConfig = subConfigIndex == 0;
                        bool isLastSubConfig = subConfigIndex == confSubConfigs.Keys.Count - 1;

                        if (isConsumeWinRTExtensions)
                        {
                            if (isCompileAsCFile)
                                throw new Error("A C file cannot be marked to consume WinRT.");
                            isCompileAsCFile = false;
                        }

                        // For now, this will do.
                        if (conf.FastBuildBlobbed && isDefaultSubConfig && !isUnity)
                        {
                            isUnity = true;
                        }
                        else
                        {
                            isUnity = false;
                        }

                        var useClr = dotNetConf && !isCompileAsNonCLRFile || isCompileAsCLRFile;
                        var fastBuildSubConfigClrSupport = useClr ? "/clr" : FileGeneratorUtilities.RemoveLineTag;

                        Trace.Assert(!isCompileAsCLRFile || !isCompileAsNonCLRFile, "Sharpmake-FastBuild : a file cannot be simultaneously compiled with and without the CLR");

                        Strings fastBuildCompilerInputPatternList = isCompileAsCFile ? new Strings { ".c" } : project.SourceFilesCPPExtensions;
                        Strings fastBuildCompilerInputPatternTransformedList = new Strings(fastBuildCompilerInputPatternList.Select((s) => { return "*" + s; }));

                        string fastBuildCompilerInputPattern = UtilityMethods.FBuildCollectionFormat(fastBuildCompilerInputPatternTransformedList, 32);

                        string fastBuildPrecompiledSourceFile = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildCompileAsC = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildUnityName = isUnity ? GetUnityName(conf) : null;

                        switch (exceptionsSetting)
                        {
                            case Options.Vc.Compiler.Exceptions.Enable:
                                scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ExceptionHandling", "/EHsc"));
                                break;
                            case Options.Vc.Compiler.Exceptions.EnableWithExternC:
                                scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ExceptionHandling", "/EHs"));
                                break;
                            case Options.Vc.Compiler.Exceptions.EnableWithSEH:
                                scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ExceptionHandling", "/EHa"));
                                break;
                        }

                        bool isNoBlobImplicitConfig = false;
                        if (conf.FastBuildNoBlobStrategy == Project.Configuration.InputFileStrategy.Exclude &&
                            conf.IsBlobbed == false &&
                            conf.FastBuildBlobbed == false
                        )
                        {
                            if (isCompileAsCPPFile == false && isCompileAsCFile == false && !isConsumeWinRTExtensions)
                            {
                                isNoBlobImplicitConfig = true;
                            }
                        }

                        string fastBuildOutputFile = CurrentBffPathKeyCombine(Util.PathGetRelative(projectPath, outputFile, true));
                        fastBuildOutputFile = platformBff.GetOutputFilename(conf.Output, fastBuildOutputFile);

                        bool useObjectLists = confUseLibraryDependencyInputs;

                        string fastBuildOutputFileShortName = GetShortProjectName(project, conf);
                        var fastBuildProjectDependencies = new Strings();
                        var fastBuildBuildOnlyDependencies = new Strings();
                        var fastBuildProjectExeUtilityDependencyList = new Strings();
                        var fastBuildTargetSubTargets = new Strings();

                        bool mustGenerateLibrary = confSubConfigs.Count > 1 && !useObjectLists && isLastSubConfig && isOutputTypeLib;

                        if (!useObjectLists && confSubConfigs.Count > 1 && !isLastSubConfig)
                        {
                            useObjectLists = true;
                        }

                        if (isOutputTypeExeOrDllOrAppleApp)
                        {
                            var orderedProjectDeps = UtilityMethods.GetOrderedFlattenedProjectDependencies(conf, false);
                            foreach (var depProjConfig in orderedProjectDeps)
                            {
                                if (depProjConfig.Project == project)
                                    throw new Error("Sharpmake-FastBuild : Project dependencies refers to itself.");
                                if (!conf.ResolvedDependencies.Contains(depProjConfig))
                                    throw new Error("Sharpmake-FastBuild : dependency was not resolved.");
                                bool isExport = depProjConfig.Project.SharpmakeProjectType == Project.ProjectTypeAttribute.Export;
                                if (isExport)
                                    continue;

                                if (depProjConfig.Output != Project.Configuration.OutputType.Exe &&
                                    depProjConfig.Output != Project.Configuration.OutputType.AppleApp &&
                                    depProjConfig.Output != Project.Configuration.OutputType.Utility)
                                {
                                    string shortProjectName = GetShortProjectName(depProjConfig.Project, depProjConfig);
                                    if (!dependenciesInfo.IgnoredLibraryNames.Contains(depProjConfig.TargetFileFullNameWithExtension))
                                        fastBuildProjectDependencies.Add(shortProjectName + "_LibraryDependency");
                                    if (depProjConfig.EventPostBuildExecute.Count != 0)
                                    {
                                        fastBuildTargetSubTargets.Add(shortProjectName);
                                    }
                                }
                                else if (!depProjConfig.IsExcludedFromBuild)
                                {
                                    fastBuildProjectExeUtilityDependencyList.Add(GetShortProjectName(depProjConfig.Project, depProjConfig));
                                }
                            }

                            orderedProjectDeps = UtilityMethods.GetOrderedFlattenedBuildOnlyDependencies(conf);
                            foreach (var depProjConfig in orderedProjectDeps)
                            {
                                if (depProjConfig.Project == project)
                                    throw new Error("Sharpmake-FastBuild : Project dependencies refers to itself.");

                                bool isExport = depProjConfig.Project.SharpmakeProjectType == Project.ProjectTypeAttribute.Export;
                                if (isExport)
                                    continue;

                                if (depProjConfig.Output != Project.Configuration.OutputType.Exe &&
                                    depProjConfig.Output != Project.Configuration.OutputType.AppleApp &&
                                    depProjConfig.Output != Project.Configuration.OutputType.Utility)
                                {
                                    fastBuildBuildOnlyDependencies.Add(GetShortProjectName(depProjConfig.Project, depProjConfig));
                                }
                                else
                                {
                                    fastBuildProjectExeUtilityDependencyList.Add(GetShortProjectName(depProjConfig.Project, depProjConfig));
                                }
                            }
                        }

                        string librarianAdditionalInputs = FileGeneratorUtilities.RemoveLineTag;

                        string outputType;
                        switch (conf.Output)
                        {
                            case Project.Configuration.OutputType.Lib:
                                outputType = "Library";
                                break;
                            case Project.Configuration.OutputType.Exe:
                            case Project.Configuration.OutputType.AppleApp:
                                outputType = "Executable";
                                break;
                            case Project.Configuration.OutputType.Dll:
                                outputType = "DLL";
                                break;
                            default:
                                outputType = "Unknown";
                                break;
                        }

                        if (confSubConfigs.Keys.Count > 1)
                        {
                            if (!isLastSubConfig)
                            {
                                fastBuildOutputFileShortName += "_" + subConfigIndex.ToString();

                                fastBuildOutputFile = Path.ChangeExtension(fastBuildOutputFile, null); // removes the extension
                                fastBuildOutputFile += "_" + subConfigIndex.ToString();
                                fastBuildOutputFile += vcxprojPlatform.StaticLibraryFileFullExtension;

                                subConfigObjectList.Add(fastBuildOutputFileShortName);
                                additionalLibs.Add(fastBuildOutputFileShortName + "_objects");
                            }
                            else
                            {
                                StringBuilder result = new StringBuilder();

                                foreach (string subConfigObject in subConfigObjectList)
                                {
                                    if (!useObjectLists && conf.Output != Project.Configuration.OutputType.Dll && conf.Output != Project.Configuration.OutputType.Exe && conf.Output != Project.Configuration.OutputType.AppleApp)
                                        fastBuildProjectDependencies.Add(subConfigObject + "_" + outputType);
                                    else
                                        fastBuildProjectDependencies.Add(subConfigObject + "_objects");
                                }
                            }
                        }

                        string fastBuildPCHForceInclude = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildCompilerPCHOptions = isUsePrecomp ? Template.ConfigurationFile.UsePrecomp : FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildCompilerPCHOptionsClang = isUsePrecomp ? Template.ConfigurationFile.UsePrecompClang : FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildCompilerDeoptimizeOptionClang = isCompileAsSwiftFile ? "-Onone" : "-O0";
                        string fastBuildLinkerOutputFile = fastBuildOutputFile;
                        string fastBuildStampExecutable = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildStampArguments = FileGeneratorUtilities.RemoveLineTag;

                        var postBuildEvents = new Dictionary<string, Project.Configuration.BuildStepBase>();

                        Strings preBuildTargets = new Strings();

                        var fastBuildTargetLibraryDependencies = new Strings();
                        {
                            if (isLastSubConfig) // post-build steps on the last subconfig
                            {
                                if (isOutputTypeExe || isOutputTypeAppleApp || conf.ExecuteTargetCopy)
                                {
                                    if (conf.CopyDependenciesBuildStep != null)
                                        throw new NotImplementedException("CopyDependenciesBuildStep are not supported with FastBuild");

                                    var copies = ProjectOptionsGenerator.ConvertPostBuildCopiesToRelative(conf, projectPath);
                                    foreach (var copy in copies)
                                    {
                                        var sourceFile = copy.Key;
                                        var destinationFolder = copy.Value;

                                        // use the global root for alias computation, as the project has not idea in which master bff it has been included
                                        var destinationRelativeToGlobal = Util.GetConvertedRelativePath(projectPath, destinationFolder, conf.Project.RootPath, true, conf.Project.RootPath);
                                        string fastBuildCopyAlias = UtilityMethods.GetFastBuildCopyAlias(Path.GetFileName(sourceFile), destinationRelativeToGlobal);
                                        fastBuildBuildOnlyDependencies.Add(fastBuildCopyAlias);
                                    }
                                }
                            }

                            // When we have a Library/Dll/Executable section, put the prebuild dependencies there (which is the last subconfig).
                            // Otherwise put it on the first object list
                            var preBuildTargetsOnLastSubconfig = isOutputTypeExeOrDllOrAppleApp || (isOutputTypeLib && !confUseLibraryDependencyInputs);
                            if ((preBuildTargetsOnLastSubconfig && isLastSubConfig) || (!preBuildTargetsOnLastSubconfig && isFirstSubConfig))
                            {
                                // the pre-steps are written in the master bff, we only need to refer their aliases
                                preBuildTargets.AddRange(conf.EventPreBuildExecute.Select(e => e.Key));
                                preBuildTargets.AddRange(conf.ResolvedEventPreBuildExe.Select(e => ProjectOptionsGenerator.MakeBuildStepName(conf, e, Vcxproj.BuildStep.PreBuild, project.RootPath, projectPath)));

                                preBuildTargets.AddRange(conf.EventCustomPrebuildExecute.Select(e => e.Key));
                                preBuildTargets.AddRange(conf.ResolvedEventCustomPreBuildExe.Select(e => ProjectOptionsGenerator.MakeBuildStepName(conf, e, Vcxproj.BuildStep.PreBuildCustomAction, project.RootPath, projectPath)));
                            }

                            fastBuildTargetSubTargets.AddRange(fastBuildProjectExeUtilityDependencyList);

                            if (conf.Output == Project.Configuration.OutputType.Lib && useObjectLists)
                            {
                                string objectList = fastBuildOutputFileShortName + "_objects";
                                fastBuildTargetLibraryDependencies.Add(objectList);
                                fastBuildTargetSubTargets.Add(objectList);
                            }
                            else if (conf.Output == Project.Configuration.OutputType.None && project.IsFastBuildAll)
                            {
                                // filter to only get the configurations of projects that were explicitly added, not the dependencies
                                var minResolvedConf = conf.ResolvedPrivateDependencies.Where(x => conf.UnResolvedPrivateDependencies.ContainsKey(x.Project.GetType()));
                                foreach (var dep in minResolvedConf)
                                {
                                    if (dep.Project.SharpmakeProjectType != Project.ProjectTypeAttribute.Export &&
                                        dep.Output != Project.Configuration.OutputType.None &&
                                        dep.Output != Project.Configuration.OutputType.Utility)
                                    {
                                        fastBuildTargetSubTargets.Add(GetShortProjectName(dep.Project, dep));
                                    }
                                }
                            }
                            else
                            {
                                string targetId = fastBuildOutputFileShortName + "_" + outputType;
                                fastBuildTargetLibraryDependencies.Add(targetId);
                                fastBuildTargetSubTargets.Add(targetId);
                            }

                            if (isLastSubConfig) // post-build steps on the last subconfig
                            {
                                foreach (var eventPair in conf.EventPostBuildExecute)
                                {
                                    fastBuildTargetSubTargets.Add(eventPair.Key);
                                    postBuildEvents.Add(eventPair.Key, eventPair.Value);
                                }

                                var extraPlatformEvents = new List<Project.Configuration.BuildStepBase>();
                                if (!FastBuildSettings.FastBuildSupportLinkerStampList && isOutputTypeExeOrDllOrAppleApp)
                                    extraPlatformEvents.AddRange(platformBff.GetExtraStampEvents(conf, fastBuildOutputFile).Select(step => { step.Resolve(resolver); return step; }));

                                extraPlatformEvents.AddRange(platformBff.GetExtraPostBuildEvents(conf, fastBuildOutputFile).Select(step => { step.Resolve(resolver); return step; }));
                                foreach (var buildEvent in extraPlatformEvents.Concat(conf.ResolvedEventPostBuildExe))
                                {
                                    string eventKey = ProjectOptionsGenerator.MakeBuildStepName(conf, buildEvent, Vcxproj.BuildStep.PostBuild, project.RootPath, projectPath);
                                    fastBuildTargetSubTargets.Add(eventKey);
                                    postBuildEvents.Add(eventKey, buildEvent);
                                }

                                foreach (var eventPair in conf.EventCustomPostBuildExecute)
                                {
                                    fastBuildTargetSubTargets.Add(eventPair.Key);
                                    postBuildEvents.Add(eventPair.Key, eventPair.Value);
                                }

                                foreach (var buildEvent in conf.ResolvedEventCustomPostBuildExe)
                                {
                                    string eventKey = ProjectOptionsGenerator.MakeBuildStepName(conf, buildEvent, Vcxproj.BuildStep.PostBuildCustomAction, project.RootPath, projectPath);
                                    fastBuildTargetSubTargets.Add(eventKey);
                                    postBuildEvents.Add(eventKey, buildEvent);
                                }

                                if (conf.PostBuildStepTest != null)
                                {
                                    string eventKey = ProjectOptionsGenerator.MakeBuildStepName(conf, conf.PostBuildStepTest, Vcxproj.BuildStep.PostBuildCustomAction, project.RootPath, projectPath);
                                    fastBuildTargetSubTargets.Add(eventKey);
                                    postBuildEvents.Add(eventKey, conf.PostBuildStepTest);
                                }
                            }

                            if (conf.Output != Project.Configuration.OutputType.Dll && conf.Output != Project.Configuration.OutputType.Exe && conf.Output != Project.Configuration.OutputType.AppleApp)
                            {
                                foreach (var subConfigObject in subConfigObjectList)
                                {
                                    string subTarget;
                                    if (useObjectLists)
                                        subTarget = subConfigObject + "_objects";
                                    else
                                        subTarget = subConfigObject + "_" + outputType;

                                    if (!fastBuildTargetSubTargets.Contains(subTarget))
                                        fastBuildTargetSubTargets.Add(subTarget);
                                    if (!fastBuildTargetLibraryDependencies.Contains(subTarget))
                                        fastBuildTargetLibraryDependencies.Add(subTarget);
                                }
                            }
                        }

                        if (additionalDependencies != null && additionalDependencies.Any())
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "AdditionalDependencies", string.Join($"'{Environment.NewLine}                            + ' ", additionalDependencies)));
                        else
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "AdditionalDependencies", FileGeneratorUtilities.RemoveLineTag));

                        string fastBuildConsumeWinRTExtension = isConsumeWinRTExtensions ? "/ZW" : FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildUsingPlatformConfig = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildSourceFileType;
                        string clangFileLanguage = string.Empty;

                        if (isCompileAsCFile)
                        {
                            fastBuildUsingPlatformConfig = platformBff.CConfigName(conf);
                            // Do not take Cpp Language conformance into account while compiling in C
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "CppLanguageStd", FileGeneratorUtilities.RemoveLineTag));
                            scopedOptions.Add(new Options.ScopedOption(confOptions, "ClangCppLanguageStandard", FileGeneratorUtilities.RemoveLineTag));
                            // and remove the stdlib specification as well
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "StdLib", FileGeneratorUtilities.RemoveLineTag));
                            // MSVC
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "LanguageStandard", FileGeneratorUtilities.RemoveLineTag));

                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ClangEnableObjC_ARC", FileGeneratorUtilities.RemoveLineTag));

                            if (clangPlatformBff != null)
                                clangFileLanguage = "-x c "; // Compiler option to indicate that its a C file
                            fastBuildSourceFileType = "/TC";
                        }
                        else if (isCompileAsObjCFile)
                        {
                            // Do not take Cpp Language conformance into account while compiling in objc
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "CppLanguageStd", FileGeneratorUtilities.RemoveLineTag));
                            scopedOptions.Add(new Options.ScopedOption(confOptions, "ClangCppLanguageStandard", FileGeneratorUtilities.RemoveLineTag));
                            // and remove the stdlib specification as well
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "StdLib", FileGeneratorUtilities.RemoveLineTag));
                            // MSVC
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "LanguageStandard", FileGeneratorUtilities.RemoveLineTag));

                            if (clangPlatformBff != null)
                                clangFileLanguage = "-x objective-c ";
                            fastBuildUsingPlatformConfig = platformBff.CConfigName(conf);

                            fastBuildSourceFileType = "";
                        }
                        else if (isCompileAsObjCPPFile)
                        {
                            // Do not take C Language conformance into account while compiling in objcpp
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "CLanguageStd", FileGeneratorUtilities.RemoveLineTag));
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ClangCLanguageStandard", FileGeneratorUtilities.RemoveLineTag));
                            // MSVC
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "LanguageStandard_C", FileGeneratorUtilities.RemoveLineTag));

                            if (clangPlatformBff != null)
                                clangFileLanguage = "-x objective-c++ ";
                            fastBuildUsingPlatformConfig = platformBff.CppConfigName(conf);

                            fastBuildSourceFileType = "";
                        }
                        else if (isCompileAsSwiftFile)
                        {
                            clangFileLanguage = "";
                            fastBuildUsingPlatformConfig = applePlatformBff.SwiftConfigName(conf);
                            fastBuildSourceFileType = "";
                        }
                        else
                        {
                            // Do not take C Language conformance into account while compiling in Cpp
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "CLanguageStd", FileGeneratorUtilities.RemoveLineTag));
                            scopedOptions.Add(new Options.ScopedOption(confOptions, "ClangCLanguageStandard", FileGeneratorUtilities.RemoveLineTag));
                            // MSVC
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "LanguageStandard_C", FileGeneratorUtilities.RemoveLineTag));

                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "ClangEnableObjC_ARC", FileGeneratorUtilities.RemoveLineTag));

                            // if files are specifically c++, we need to add the language flag to make sure the compiler sees them as c++
                            if (isCompileAsCPPFile && clangPlatformBff != null)
                                clangFileLanguage = "-x c++ ";

                            fastBuildSourceFileType = "/TP";
                            fastBuildUsingPlatformConfig = platformBff.CppConfigName(conf);
                        }

                        // TODOANT: Add nasm/masm change
                        if (isASMFileSection)
                        {
                            fastBuildUsingPlatformConfig += Template.ConfigurationFile.MasmConfigNameSuffix;
                        }
                        if (isNASMFileSection)
                        {
                            fastBuildUsingPlatformConfig += Template.ConfigurationFile.NasmConfigNameSuffix;
                        }

                        string fastBuildCompilerExtraOptions = Template.ConfigurationFile.CPPCompilerExtraOptions;
                        if (isASMFileSection)
                        {
                            fastBuildCompilerExtraOptions = Template.ConfigurationFile.MasmCompilerExtraOptions;
                        }
                        if (isNASMFileSection)
                        {
                            fastBuildCompilerExtraOptions = Template.ConfigurationFile.NasmCompilerExtraOptions;
                        }

                        string fastBuildCompilerOptionsDeoptimize = FileGeneratorUtilities.RemoveLineTag;
                        if (!isASMFileSection && conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                            fastBuildCompilerOptionsDeoptimize = Template.ConfigurationFile.CPPCompilerOptionsDeoptimize;

                        string compilerOptions = Template.ConfigurationFile.CompilerOptionsCPP;
                        if (isASMFileSection)
                        {
                            compilerOptions = Template.ConfigurationFile.CompilerOptionsMasm;
                        }
                        if (isNASMFileSection)
                        {
                            compilerOptions = Template.ConfigurationFile.CompilerOptionsNasm;
                        }
                        compilerOptions += Template.ConfigurationFile.CompilerOptionsCommon;

                        string compilerOptionsClang = Template.ConfigurationFile.CompilerOptionsClang;
                        if (isNASMFileSection)
                        {
                            compilerOptionsClang = Template.ConfigurationFile.CompilerOptionsNasm;
                        }
                        compilerOptionsClang += Template.ConfigurationFile.CompilerOptionsCommon;

                        string fastBuildDeoptimizationWritableFiles = null;
                        string fastBuildDeoptimizationWritableFilesWithToken = null;
                        Project.Configuration.DeoptimizationWritableFiles deoptimizeSetting = conf.FastBuildDeoptimization;
                        if (isASMFileSection)
                            deoptimizeSetting = Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization;
                        switch (deoptimizeSetting)
                        {
                            case Project.Configuration.DeoptimizationWritableFiles.DeoptimizeWritableFiles:
                                fastBuildDeoptimizationWritableFiles = "true";
                                fastBuildDeoptimizationWritableFilesWithToken = FileGeneratorUtilities.RemoveLineTag;
                                break;
                            case Project.Configuration.DeoptimizationWritableFiles.DeoptimizeWritableFilesWithToken:
                                fastBuildDeoptimizationWritableFiles = FileGeneratorUtilities.RemoveLineTag;
                                fastBuildDeoptimizationWritableFilesWithToken = "true";
                                break;

                            default:
                                fastBuildDeoptimizationWritableFiles = FileGeneratorUtilities.RemoveLineTag;
                                fastBuildDeoptimizationWritableFilesWithToken = FileGeneratorUtilities.RemoveLineTag;
                                break;
                        }

                        string fastBuildCompilerForceUsing = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildAdditionalCompilerOptionsFromCode = FileGeneratorUtilities.RemoveLineTag;

                        if (conf.ReferencesByPath.Count > 0)  // only ref by path supported
                        {
                            fastBuildAdditionalCompilerOptionsFromCode = "";
                            foreach (var refByPath in conf.ReferencesByPath)
                            {
                                string refByPathCopy = refByPath;
                                if (ShouldMakePathRelative(refByPath, context.Project))
                                    refByPathCopy = CurrentBffPathKeyCombine(Util.PathGetRelative(context.ProjectDirectory, refByPath));

                                fastBuildAdditionalCompilerOptionsFromCode += "/FU\"" + refByPathCopy + "\" ";
                            }
                        }

                        string llvmClangCompilerOptions = null;
                        if (!isConsumeWinRTExtensions)
                        {
                            var platformToolset = Options.GetObject<Options.Vc.General.PlatformToolset>(conf);
                            if (platformToolset.IsLLVMToolchain() && Options.GetObject<Options.Vc.LLVM.UseClangCl>(context.Configuration) == Options.Vc.LLVM.UseClangCl.Enable)
                            {
                                switch (platformToolset)
                                {
                                    case Options.Vc.General.PlatformToolset.LLVM:
                                    case Options.Vc.General.PlatformToolset.ClangCL:
                                        llvmClangCompilerOptions = "-m64"; // -m$(PlatformArchitecture)
                                        fastBuildPCHForceInclude = @"/FI""[cmdLineOptions.PrecompiledHeaderThrough]""";


                                        // <!-- Set the value of _MSC_VER and _MSC_FULL_VER to claim for compatibility -->
                                        Project.Configuration.FastBuildClangMscVersionDetectionType detectionType = conf.FastBuildClangMscVersionDetectionInfo;
                                        string overridenMscVer = Options.GetString<Options.Clang.Compiler.MscVersion>(conf);
                                        Options.Vc.General.PlatformToolset overridenPlatformToolset = Options.Vc.General.PlatformToolset.Default;
                                        Options.WithArgOption<Options.Vc.General.PlatformToolset>.Get<Options.Clang.Compiler.LLVMVcPlatformToolset>(conf, ref overridenPlatformToolset);

                                        CompilerVersionForClangCl detectedVersion = DetectCompilerVersionForClangCl(
                                            detectionType, overridenMscVer, overridenPlatformToolset, context.DevelopmentEnvironment, conf.Target.GetPlatform());

                                        switch (detectedVersion.versionType)
                                        {
                                            case CompilerVersionForClangClType.MscVersion :
                                                llvmClangCompilerOptions += string.Format(" -fmsc-version={0}", detectedVersion.mscVersion);
                                                break;
                                            case CompilerVersionForClangClType.MsCompatibilityVersion :
                                                llvmClangCompilerOptions += string.Format(" -fms-compatibility-version={0}.{1}.{2}", detectedVersion.msCompatibilityVersion.Major, detectedVersion.msCompatibilityVersion.Minor, detectedVersion.msCompatibilityVersion.Build);
                                                break;
                                        }
                                        
                                        break;
                                }
                            }
                        }

                        if (!string.IsNullOrEmpty(llvmClangCompilerOptions))
                        {
                            if (fastBuildAdditionalCompilerOptionsFromCode == FileGeneratorUtilities.RemoveLineTag)
                                fastBuildAdditionalCompilerOptionsFromCode = llvmClangCompilerOptions;
                            else
                                fastBuildAdditionalCompilerOptionsFromCode += " " + llvmClangCompilerOptions;
                        }

                        // c1xx: warning C4199: two-phase name lookup is not supported for C++/CLI, C++/CX, or OpenMP; use /Zc:twoPhase-
                        if (isConsumeWinRTExtensions && context.DevelopmentEnvironment >= DevEnv.vs2017)
                        {
                            if (conf.AdditionalCompilerOptions.Contains("/permissive-") && !conf.AdditionalCompilerOptions.Contains("/Zc:twoPhase-"))
                            {
                                if (fastBuildAdditionalCompilerOptionsFromCode == FileGeneratorUtilities.RemoveLineTag)
                                    fastBuildAdditionalCompilerOptionsFromCode = "/Zc:twoPhase-";
                                else
                                    fastBuildAdditionalCompilerOptionsFromCode += " /Zc:twoPhase-";
                            }
                        }

                        if (conf.ReferencesByName.Count > 0)
                        {
                            throw new Exception("Use ReferencesByPath instead of ReferencesByName for FastBuild support; ");
                        }

                        if (conf.ForceUsingDependencies.Any() || conf.DependenciesForceUsingFiles.Any() || conf.ForceUsingFiles.Any())
                        {
                            StringBuilder builderForceUsingFiles = new StringBuilder();
                            foreach (var fuConfig in conf.ForceUsingDependencies)
                            {
                                builderForceUsingFiles.AppendFormat(@" /FU""{0}.dll""", fuConfig.TargetFileFullName);
                            }
                            foreach (var f in conf.ForceUsingFiles.Union(conf.DependenciesForceUsingFiles))
                            {
                                string file = f;
                                if (ShouldMakePathRelative(f, context.Project))
                                    file = CurrentBffPathKeyCombine(Util.PathGetRelative(context.ProjectDirectory, f));

                                builderForceUsingFiles.AppendFormat(@" /FU""{0}""", file);
                            }
                            fastBuildCompilerForceUsing = builderForceUsingFiles.ToString();
                        }

                        if (isOutputTypeExeOrDllOrAppleApp)
                        {
                            var extraPlatformEvents = new List<Project.Configuration.BuildStepExecutable>();
                            if (FastBuildSettings.FastBuildSupportLinkerStampList)
                                extraPlatformEvents.AddRange(platformBff.GetExtraStampEvents(conf, fastBuildOutputFile).Select(step => { step.Resolve(resolver); return step; }));

                            if (conf.PostBuildStampExe != null || conf.PostBuildStampExes.Any() || extraPlatformEvents.Any())
                            {
                                var fastbuildStampExecutableList = new List<string>();
                                var fastBuildStampArgumentsList = new List<string>();

                                foreach (var stampExe in extraPlatformEvents.Concat(conf.PostBuildStampExes.Prepend(conf.PostBuildStampExe)).Where(x => x != null))
                                {
                                    fastbuildStampExecutableList.Add(CurrentBffPathKeyCombine(Util.PathGetRelative(projectPath, stampExe.ExecutableFile, true)));
                                    fastBuildStampArgumentsList.Add(string.Format("{0} {1} {2}",
                                        stampExe.ExecutableInputFileArgumentOption,
                                        stampExe.ExecutableOutputFileArgumentOption,
                                        stampExe.ExecutableOtherArguments));
                                }

                                fastBuildStampExecutable = UtilityMethods.FBuildFormatList(fastbuildStampExecutableList, 30);
                                fastBuildStampArguments = UtilityMethods.FBuildFormatList(fastBuildStampArgumentsList, 30);
                            }
                        }

                        bool linkObjects = false;
                        if (isOutputTypeExeOrDllOrAppleApp)
                        {
                            linkObjects = confUseLibraryDependencyInputs;
                        }

                        Strings fullInputPaths = new Strings();
                        string fastBuildInputPath = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildInputExcludedFiles = FileGeneratorUtilities.RemoveLineTag;
                        {
                            Strings excludedSourceFiles = new Strings();
                            if (isNoBlobImplicitConfig && isDefaultSubConfig)
                            {
                                fullInputPaths.Add(context.ProjectSourceCapitalized);
                                fullInputPaths.AddRange(project.AdditionalSourceRootPaths.Select(Util.GetCapitalizedPath));

                                excludedSourceFiles.AddRange(filesInNonDefaultSection.Select(f => f.FileName));
                            }

                            if (isDefaultSubConfig && conf.FastBuildBlobbingStrategy == Project.Configuration.InputFileStrategy.Exclude && conf.FastBuildBlobbed)
                            {
                                // Adding the folders excluded from unity to the folders to build without unity(building each file individually)
                                fullInputPaths.AddRange(project.SourcePathsBlobExclude.Select(Util.GetCapitalizedPath));
                            }

                            if (project.SourceFilesFiltersRegex.Count == 0)
                            {
                                var relativePaths = new Strings(fullInputPaths.Select(p => CurrentBffPathKeyCombine(Util.PathGetRelative(context.ProjectDirectory, p, true))));
                                fastBuildInputPath = UtilityMethods.FBuildCollectionFormat(relativePaths, 32);
                            }
                            else
                            {
                                fullInputPaths.Clear();
                            }

                            excludedSourceFiles.AddRange(conf.ResolvedSourceFilesBuildExclude);
                            excludedSourceFiles.AddRange(conf.PrecompSourceExclude);

                            // Converting the excluded filenames to relative path to the input path so that this
                            // can work properly with subst usage when running with fastbuild caching active.
                            //
                            // Also exclusion checks in fastbuild assume that the exclusion filenames are
                            // relative to the .UnityInputPath and checks that paths are ending with the specified
                            // path which means that any filename starting with a .. will never be excluded by fastbuild.
                            //
                            // Note: Ideally fastbuild should expect relative paths to the bff file path instead of the .UnityInputPath but
                            // well I guess we are stuck with this.
                            var excludedSourceFilesRelative = new Strings();
                            foreach (string file in excludedSourceFiles.SortedValues)
                            {
                                string fileExtension = Path.GetExtension(file);
                                if (project.SourceFilesCompileExtensions.Contains(fileExtension))
                                {
                                    if (IsFileInInputPathList(fullInputPaths, file))
                                        excludedSourceFilesRelative.Add(CurrentBffPathKeyCombine(Util.PathGetRelative(context.ProjectDirectoryCapitalized, file)));
                                }
                            }
                            if (excludedSourceFilesRelative.Count > 0)
                            {
                                Strings includedExtensions = isCompileAsCFile ? new Strings { ".c" } : project.SourceFilesCPPExtensions;
                                fastBuildInputExcludedFiles = UtilityMethods.FBuildCollectionFormat(excludedSourceFilesRelative, 34, includedExtensions);
                            }
                        }

                        bool projectHasResourceFiles = false;
                        bool projectHasEmbeddedResources = false;
                        string fastBuildSourceFiles = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildResourceFiles = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildEmbeddedResources = FileGeneratorUtilities.RemoveLineTag;
                        string fastBuildEmbeddedOutputPrefix = conf.EmbeddedResourceOutputPrefix;

                        {
                            List<string> fastbuildSourceFilesList = new List<string>();
                            List<string> fastbuildResourceFilesList = new List<string>();
                            List<string> fastbuildEmbeddedResourceFilesList = new List<string>();

                            var sourceFiles = confSubConfigs[subConfig];
                            foreach (var sourceFile in sourceFiles)
                            {
                                string sourceFileName = CurrentBffPathKeyCombine(sourceFile.FileNameProjectRelative);

                                if (isUsePrecomp && conf.PrecompSource != null && sourceFile.FileName.EndsWith(conf.PrecompSource, StringComparison.OrdinalIgnoreCase))
                                {
                                    fastBuildPrecompiledSourceFile = sourceFileName;
                                }
                                else if (string.Compare(sourceFile.FileExtension, ".rc", StringComparison.OrdinalIgnoreCase) == 0)
                                {
                                    if (microsoftPlatformBff != null && microsoftPlatformBff.SupportsResourceFiles)
                                    {
                                        fastbuildResourceFilesList.Add(sourceFileName);
                                        projectHasResourceFiles = true;
                                    }
                                }
                                else if (string.Compare(sourceFile.FileExtension, ".resx", StringComparison.OrdinalIgnoreCase) == 0)
                                {
                                    if (microsoftPlatformBff != null && microsoftPlatformBff.SupportsResourceFiles)
                                    {
                                        fastbuildEmbeddedResourceFilesList.Add(sourceFileName);
                                        projectHasEmbeddedResources = true;
                                    }
                                }
                                else
                                {
                                    bool isSourceFileExtension = project.SourceFilesCompileExtensions.Contains(sourceFile.FileExtension);
                                    bool isBlobbed = project.SourceFilesBlobExtensions.Contains(sourceFile.FileExtension);
                                    if ((isSourceFileExtension && !isBlobbed) ||
                                        conf.ResolvedSourceFilesBlobExclude.Contains(sourceFile.FileName) ||
                                        isNoBlobImplicitConfig ||
                                        !isUnity)
                                    {
                                        if (!IsFileInInputPathList(fullInputPaths, sourceFile.FileName))
                                            fastbuildSourceFilesList.Add(sourceFileName);
                                    }
                                }
                            }
                            fastBuildSourceFiles = UtilityMethods.FBuildFormatList(fastbuildSourceFilesList, 32);
                            fastBuildResourceFiles = UtilityMethods.FBuildFormatList(fastbuildResourceFilesList, 30);
                            fastBuildEmbeddedResources = UtilityMethods.FBuildFormatList(fastbuildEmbeddedResourceFilesList, 30);
                        }

                        var fileCustomBuildKeys = new Strings();
                        UtilityMethods.WriteConfigCustomBuildStepsAsGenericExecutable(context.ProjectDirectoryCapitalized, bffGenerator, context.Project, conf,
                            key =>
                            {
                                if (!allFileCustomBuild.TryGetValue(key.Description, out var alreadyRegistered))
                                {
                                    allFileCustomBuild.Add(key.Description, key);
                                    bffGenerator.Write(Template.ConfigurationFile.GenericExecutableSection);
                                }
                                else if (key.Executable != alreadyRegistered.Executable ||
                                        key.KeyInput != alreadyRegistered.KeyInput ||
                                        key.Output != alreadyRegistered.Output ||
                                        key.ExecutableArguments != alreadyRegistered.ExecutableArguments)
                                {
                                    throw new Exception(string.Format("Command key '{0}' duplicates another command.  Command is:\n{1}", key, bffGenerator.Resolver.Resolve(Template.ConfigurationFile.GenericExecutableSection)));
                                }

                                fileCustomBuildKeys.Add(key.Description);

                                return false;
                            });

                        Strings fastBuildPreBuildDependencies = new Strings();
                        var orderedForceUsingDeps = UtilityMethods.GetOrderedFlattenedProjectDependencies(conf, false, true);
                        fastBuildPreBuildDependencies.AddRange(orderedForceUsingDeps.Select(dep => GetShortProjectName(dep.Project, dep)));

                        // fastBuildBuildOnlyDependencies only gets added to exe/dll sections.
                        // Add the prebuild steps to fastBuildPreBuildDependencies if we are building a lib
                        if (isOutputTypeExeOrDllOrAppleApp)
                        {
                            fastBuildBuildOnlyDependencies.AddRange(preBuildTargets);
                            fastBuildBuildOnlyDependencies.AddRange(fileCustomBuildKeys);
                        }
                        else if (isOutputTypeLib)
                        {
                            fastBuildPreBuildDependencies.AddRange(preBuildTargets);
                            if (isLastSubConfig)
                                fastBuildPreBuildDependencies.AddRange(fileCustomBuildKeys);
                        }

                        if (projectHasResourceFiles)
                            resourceFilesSections.Add(fastBuildOutputFileShortName + "_resources");
                        if (projectHasEmbeddedResources)
                        {
                            embeddedResourceFilesSections.Add(fastBuildOutputFileShortName + "_embedded");
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "EmbedResources", "/ASSEMBLYRESOURCE:\"%3\""));
                        }
                        else
                        {
                            scopedOptions.Add(new Options.ScopedOption(confCmdLineOptions, "EmbedResources", FileGeneratorUtilities.RemoveLineTag));
                        }

                        if (mustGenerateLibrary)
                        {
                            librarianAdditionalInputs = UtilityMethods.FBuildFormatList(additionalLibs, 33);
                        }

                        // It is useless to have an input pattern defined if there is no input path
                        if (fastBuildInputPath == FileGeneratorUtilities.RemoveLineTag)
                            fastBuildCompilerInputPattern = FileGeneratorUtilities.RemoveLineTag;

                        fastBuildProjectDependencies.AddRange(resourceFilesSections);
                        fastBuildProjectDependencies.Add("[fastBuildOutputFileShortName]_objects");
                        string fastBuildObjectListEmbeddedResources = FormatListPartForTag(embeddedResourceFilesSections, 32, true);

                        string fastBuildInputFilesRootPath = FileGeneratorUtilities.RemoveLineTag;

                        if (conf.FastBuildInputFilesRootPath != null)
                        {
                            fastBuildInputFilesRootPath = CurrentBffPathKeyCombine(Util.PathGetRelative(context.ProjectDirectory, conf.FastBuildInputFilesRootPath));
                        }

                        using (bffGenerator.Declare("conf", conf))
                        using (bffGenerator.Declare("project", project))
                        using (bffGenerator.Declare("target", conf.Target))
                        {
                            switch (conf.Output)
                            {
                                case Project.Configuration.OutputType.Lib:
                                case Project.Configuration.OutputType.Exe:
                                case Project.Configuration.OutputType.AppleApp:
                                case Project.Configuration.OutputType.Dll:
                                    using (bffGenerator.Declare("$(ProjectName)", projectName))
                                    using (bffGenerator.Declare("options", confOptions))
                                    using (bffGenerator.Declare("cmdLineOptions", confCmdLineOptions))
                                    using (bffGenerator.Declare("fastBuildUsingPlatformConfig", "Using( " + fastBuildUsingPlatformConfig + " )"))
                                    using (bffGenerator.Declare("fastBuildProjectName", projectName))
                                    using (bffGenerator.Declare("fastBuildClrSupport", fastBuildSubConfigClrSupport))
                                    using (bffGenerator.Declare("fastBuildOutputFileShortName", fastBuildOutputFileShortName))
                                    using (bffGenerator.Declare("fastBuildOutputFile", fastBuildOutputFile))
                                    using (bffGenerator.Declare("fastBuildLinkerOutputFile", fastBuildLinkerOutputFile))
                                    using (bffGenerator.Declare("fastBuildLinkerLinkObjects", linkObjects ? "true" : "false"))
                                    using (bffGenerator.Declare("fastBuildInputPath", fastBuildInputPath))
                                    using (bffGenerator.Declare("fastBuildCompilerInputPattern", fastBuildCompilerInputPattern))
                                    using (bffGenerator.Declare("fastBuildInputExcludedFiles", fastBuildInputExcludedFiles))
                                    using (bffGenerator.Declare("fastBuildSourceFiles", fastBuildSourceFiles))
                                    using (bffGenerator.Declare("fastBuildResourceFiles", fastBuildResourceFiles))
                                    using (bffGenerator.Declare("fastBuildEmbeddedResources", fastBuildEmbeddedResources))
                                    using (bffGenerator.Declare("fastBuildPrecompiledSourceFile", fastBuildPrecompiledSourceFile))
                                    using (bffGenerator.Declare("fastBuildProjectDependencies", UtilityMethods.FBuildFormatList(fastBuildProjectDependencies.Values, 30)))
                                    using (bffGenerator.Declare("fastBuildBuildOnlyDependencies", UtilityMethods.FBuildFormatList(fastBuildBuildOnlyDependencies.Values, 30)))
                                    using (bffGenerator.Declare("fastBuildPreBuildTargets", UtilityMethods.FBuildFormatList(fastBuildPreBuildDependencies.Values, 28)))
                                    using (bffGenerator.Declare("fastBuildObjectListEmbeddedResources", fastBuildObjectListEmbeddedResources))
                                    using (bffGenerator.Declare("fastBuildCompilerPCHOptions", fastBuildCompilerPCHOptions))
                                    using (bffGenerator.Declare("fastBuildCompilerPCHOptionsClang", fastBuildCompilerPCHOptionsClang))
                                    using (bffGenerator.Declare("fastBuildCompilerDeoptimizeOptionClang", fastBuildCompilerDeoptimizeOptionClang))
                                    using (bffGenerator.Declare("fastBuildPCHForceInclude", isUsePrecomp ? fastBuildPCHForceInclude : FileGeneratorUtilities.RemoveLineTag))
                                    using (bffGenerator.Declare("fastBuildConsumeWinRTExtension", fastBuildConsumeWinRTExtension))
                                    using (bffGenerator.Declare("fastBuildOutputType", outputType))
                                    using (bffGenerator.Declare("fastBuildLibrarianAdditionalInputs", librarianAdditionalInputs))
                                    using (bffGenerator.Declare("fastBuildCompileAsC", fastBuildCompileAsC))
                                    using (bffGenerator.Declare("fastBuildUnityName", fastBuildUnityName ?? FileGeneratorUtilities.RemoveLineTag))
                                    using (bffGenerator.Declare("fastBuildInputFilesRootPath", fastBuildInputFilesRootPath))
                                    using (bffGenerator.Declare("fastBuildClangFileLanguage", clangFileLanguage))
                                    using (bffGenerator.Declare("fastBuildDeoptimizationWritableFiles", fastBuildDeoptimizationWritableFiles))
                                    using (bffGenerator.Declare("fastBuildDeoptimizationWritableFilesWithToken", fastBuildDeoptimizationWritableFilesWithToken))
                                    using (bffGenerator.Declare("fastBuildCompilerForceUsing", fastBuildCompilerForceUsing))
                                    using (bffGenerator.Declare("fastBuildSourceFileType", fastBuildSourceFileType))
                                    using (bffGenerator.Declare("fastBuildAdditionalCompilerOptionsFromCode", fastBuildAdditionalCompilerOptionsFromCode))
                                    using (bffGenerator.Declare("fastBuildStampExecutable", fastBuildStampExecutable))
                                    using (bffGenerator.Declare("fastBuildStampArguments", fastBuildStampArguments))
                                    using (bffGenerator.Declare("fastBuildEmbeddedOutputPrefix", fastBuildEmbeddedOutputPrefix))
                                    using (bffGenerator.Declare("fastbuildConcurrencyGroupName", conf.FastBuildLinkConcurrencyGroup ?? FileGeneratorUtilities.RemoveLineTag))
                                    {
                                        if (projectHasResourceFiles)
                                        {
                                            bffGenerator.Write(Template.ConfigurationFile.ResourcesBeginSection);
                                            bffGenerator.Write(Template.ConfigurationFile.ResourceCompilerExtraOptions);
                                            bffGenerator.Write(Template.ConfigurationFile.ResourceCompilerOptions);
                                            bffGenerator.Write(Template.ConfigurationFile.EndSection);
                                        }

                                        if (projectHasEmbeddedResources)
                                        {
                                            // Only declare the compiler here to avoid potential exceptions caused by GetFragment in targets without a .Net framework
                                            using (bffGenerator.Declare("fastBuildEmbeddedResourceCompiler", KitsRootPaths.GetNETFXToolsDir(conf.Target.GetFragment<DotNetFramework>()) + "resgen.exe"))
                                            {
                                                bffGenerator.Write(Template.ConfigurationFile.EmbeddedResourcesBeginSection);
                                                bffGenerator.Write(Template.ConfigurationFile.EmbeddedResourceCompilerOptions);
                                                bffGenerator.Write(Template.ConfigurationFile.EndSection);
                                            }
                                        }

                                        // Exe, DLL and AppleApp will always add an extra objectlist
                                        if (isOutputTypeExeOrDllOrAppleApp && isLastSubConfig // only last subconfig will generate objectlist
                                        )
                                        {
                                            bffGenerator.Write(Template.ConfigurationFile.ObjectListBeginSection);

                                            if (conf.Platform.IsMicrosoft())
                                            {
                                                bffGenerator.Write(fastBuildCompilerExtraOptions);
                                                bffGenerator.Write(Template.ConfigurationFile.CPPCompilerOptimizationOptions);

                                                if (isUsePrecomp)
                                                    bffGenerator.Write(Template.ConfigurationFile.PCHOptions);
                                                bffGenerator.Write(compilerOptions);
                                                if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                {
                                                    if (isUsePrecomp)
                                                        bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                    bffGenerator.Write(fastBuildCompilerOptionsDeoptimize);
                                                    bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                }
                                            }
                                            else
                                            {
                                                if (isCompileAsSwiftFile)
                                                    applePlatformBff?.SetupSwiftOptions(bffGenerator);
                                                else  if (!isNASMFileSection)
                                                    clangPlatformBff?.SetupClangOptions(bffGenerator); // TODO: This checks twice if the platform supports Clang -- fix?
                                                else
                                                    bffGenerator.Write(fastBuildCompilerExtraOptions);

                                                if (conf.Platform.IsUsingClang())
                                                {
                                                    if (isUsePrecomp)
                                                        bffGenerator.Write(Template.ConfigurationFile.PCHOptionsClang);
                                                    bffGenerator.Write(compilerOptionsClang);
                                                    if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                    {
                                                        if (isUsePrecomp)
                                                            bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                        bffGenerator.Write(Template.ConfigurationFile.ClangCompilerOptionsDeoptimize);
                                                        bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                    }
                                                }
                                            }

                                            if (fastBuildPreBuildDependencies.Any())
                                                bffGenerator.Write(Template.ConfigurationFile.PreBuildDependencies);

                                            bffGenerator.Write(Template.ConfigurationFile.EndSection);
                                        }

                                        if (isOutputTypeDll && !isLastSubConfig)
                                        {
                                            bffGenerator.Write(Template.ConfigurationFile.ObjectListBeginSection);

                                            if (conf.Platform.IsMicrosoft())
                                            {
                                                bffGenerator.Write(fastBuildCompilerExtraOptions);
                                                bffGenerator.Write(Template.ConfigurationFile.CPPCompilerOptimizationOptions);

                                                if (isUsePrecomp)
                                                    bffGenerator.Write(Template.ConfigurationFile.PCHOptions);
                                                bffGenerator.Write(compilerOptions);
                                                if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                {
                                                    if (isUsePrecomp)
                                                        bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                    bffGenerator.Write(fastBuildCompilerOptionsDeoptimize);
                                                    bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                }
                                            }
                                            else
                                            {
                                                if (isCompileAsSwiftFile)
                                                    applePlatformBff?.SetupSwiftOptions(bffGenerator);
                                                else if (!isNASMFileSection)
                                                    clangPlatformBff?.SetupClangOptions(bffGenerator);  // TODO: This checks twice if the platform supports Clang -- fix?
                                                else
                                                    bffGenerator.Write(fastBuildCompilerExtraOptions);

                                                if (conf.Platform.IsUsingClang())
                                                {
                                                    if (isUsePrecomp)
                                                        bffGenerator.Write(Template.ConfigurationFile.PCHOptionsClang);
                                                    bffGenerator.Write(compilerOptionsClang);

                                                    if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                    {
                                                        if (isUsePrecomp)
                                                            bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                        bffGenerator.Write(Template.ConfigurationFile.ClangCompilerOptionsDeoptimize);
                                                        bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                    }
                                                }

                                                // TODO: Add BFF generation for Win64 on Windows/Mac/Linux?
                                            }

                                            if (fastBuildPreBuildDependencies.Any())
                                                bffGenerator.Write(Template.ConfigurationFile.PreBuildDependencies);

                                            bffGenerator.Write(Template.ConfigurationFile.EndSection);
                                        }
                                        else
                                        {
                                            bool outputLib = false;
                                            string beginSectionType = null;
                                            switch (conf.Output)
                                            {
                                                case Project.Configuration.OutputType.AppleApp:
                                                case Project.Configuration.OutputType.Exe:
                                                    {
                                                        if (isLastSubConfig)
                                                        {
                                                            beginSectionType = Template.ConfigurationFile.ExeDllBeginSection;
                                                        }
                                                        else
                                                        {
                                                            // in the case the lib has the flag force to be an objectlist, change the template
                                                            if (useObjectLists)
                                                                beginSectionType = Template.ConfigurationFile.ObjectListBeginSection;
                                                            else
                                                                beginSectionType = Template.ConfigurationFile.LibBeginSection;
                                                            outputLib = true;
                                                        }
                                                    }
                                                    break;
                                                case Project.Configuration.OutputType.Dll:
                                                    {
                                                        beginSectionType = Template.ConfigurationFile.ExeDllBeginSection;
                                                    }
                                                    break;
                                                case Project.Configuration.OutputType.Lib:
                                                    {
                                                        // in the case the lib has the flag force to be an objectlist, change the template
                                                        if (useObjectLists)
                                                            beginSectionType = Template.ConfigurationFile.ObjectListBeginSection;
                                                        else
                                                            beginSectionType = Template.ConfigurationFile.LibBeginSection;
                                                        outputLib = true;
                                                    }
                                                    break;
                                            }

                                            bffGenerator.Write(beginSectionType);

                                            if (outputLib)
                                            {
                                                if (conf.Platform.IsMicrosoft())
                                                {
                                                    bffGenerator.Write(fastBuildCompilerExtraOptions);
                                                    bffGenerator.Write(Template.ConfigurationFile.CPPCompilerOptimizationOptions);

                                                    if (isUsePrecomp)
                                                        bffGenerator.Write(Template.ConfigurationFile.PCHOptions);

                                                    bffGenerator.Write(compilerOptions);

                                                    if (!useObjectLists)
                                                    {
                                                        bffGenerator.Write(Template.ConfigurationFile.LibrarianAdditionalInputs);
                                                        bffGenerator.Write(Template.ConfigurationFile.LibrarianOptions);
                                                    }
                                                    if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                    {
                                                        if (isUsePrecomp)
                                                            bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                        bffGenerator.Write(fastBuildCompilerOptionsDeoptimize);
                                                        bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                    }
                                                }
                                                else
                                                {
                                                    if (isCompileAsSwiftFile)
                                                        applePlatformBff?.SetupSwiftOptions(bffGenerator);
                                                    else if (!isNASMFileSection)
                                                        clangPlatformBff?.SetupClangOptions(bffGenerator);  // TODO: This checks twice if the platform supports Clang -- fix?
                                                    else
                                                        bffGenerator.Write(fastBuildCompilerExtraOptions);;

                                                    if (conf.Platform.IsUsingClang())
                                                    {
                                                        if (isUsePrecomp)
                                                            bffGenerator.Write(Template.ConfigurationFile.PCHOptionsClang);

                                                        bffGenerator.Write(compilerOptionsClang);
                                                        if (conf.FastBuildDeoptimization != Project.Configuration.DeoptimizationWritableFiles.NoDeoptimization)
                                                        {
                                                            if (isUsePrecomp)
                                                                bffGenerator.Write(Template.ConfigurationFile.PCHOptionsDeoptimize);
                                                            bffGenerator.Write(Template.ConfigurationFile.ClangCompilerOptionsDeoptimize);
                                                            bffGenerator.Write(Template.ConfigurationFile.DeOptimizeOption);
                                                        }
                                                        if (!useObjectLists)
                                                        {
                                                            bffGenerator.Write(Template.ConfigurationFile.LibrarianAdditionalInputs);
                                                            bffGenerator.Write(Template.ConfigurationFile.LibrarianOptionsClang);
                                                        }
                                                    }
                                                }

                                                if (fastBuildPreBuildDependencies.Any())
                                                    bffGenerator.Write(Template.ConfigurationFile.PreBuildDependencies);
                                            }
                                            else
                                            {
                                                platformBff.SetupExtraLinkerSettings(bffGenerator, conf, fastBuildOutputFile);
                                            }

                                            bffGenerator.Write(Template.ConfigurationFile.EndSection);

                                            // Resolve node name of the prebuild dependency for PostBuildEvents.
                                            string resolvedSectionNodeIdentifier;
                                            if (beginSectionType == Template.ConfigurationFile.ObjectListBeginSection)
                                            {
                                                resolvedSectionNodeIdentifier = resolver.Resolve("[fastBuildOutputFileShortName]_objects");
                                            }
                                            else
                                            {
                                                resolvedSectionNodeIdentifier = resolver.Resolve("[fastBuildOutputFileShortName]_[fastBuildOutputType]");
                                            }

                                            // Convert build steps to Bff resolvable objects
                                            var resolvableBuildSteps = UtilityMethods.GetBffNodesFromBuildSteps(postBuildEvents, new Strings(resolvedSectionNodeIdentifier));
                                            // Resolve objects using the current project path
                                            var resolvedBuildSteps = resolvableBuildSteps.Select(b => b.Resolve(project.RootPath, projectPath, resolver));

                                            foreach (var buildStep in resolvedBuildSteps)
                                            {
                                                bffGenerator.Write(buildStep);
                                            }

                                            // Write Target Alias
                                            if (isLastSubConfig)
                                            {
                                                string genLibName = "'" + fastBuildOutputFileShortName + "_" + outputType + "'";
                                                using (bffGenerator.Declare("fastBuildTargetSubTargets", mustGenerateLibrary ? genLibName : UtilityMethods.FBuildFormatList(fastBuildTargetSubTargets.Values, 15)))
                                                using (bffGenerator.Declare("fastBuildOutputFileShortName", fastBuildOutputFileShortName))
                                                using (bffGenerator.Declare("fastBuildTargetLibraryDependencies", mustGenerateLibrary ? genLibName : UtilityMethods.FBuildFormatList(fastBuildTargetLibraryDependencies.Values, 15)))
                                                {
                                                    bffGenerator.Write(Template.ConfigurationFile.TargetSection);
                                                    bffGenerator.Write(Template.ConfigurationFile.TargetForLibraryDependencySection);
                                                }
                                            }
                                        }
                                    }
                                    break;
                                case Project.Configuration.OutputType.None:
                                    {
                                        // Write Target Alias
                                        using (bffGenerator.Declare("fastBuildOutputFileShortName", fastBuildOutputFileShortName))
                                        using (bffGenerator.Declare("fastBuildTargetSubTargets", UtilityMethods.FBuildFormatList(fastBuildTargetSubTargets.Values, 15)))
                                        using (bffGenerator.Declare("fastBuildTargetLibraryDependencies", UtilityMethods.FBuildFormatList(fastBuildTargetLibraryDependencies.Values, 15)))
                                        {
                                            bffGenerator.Write(Template.ConfigurationFile.TargetSection);
                                            if (!project.IsFastBuildAll)
                                                bffGenerator.Write(Template.ConfigurationFile.TargetForLibraryDependencySection);
                                        }
                                    }
                                    break;
                            }
                        }

                        scopedOptions.ForEach(scopedOption => scopedOption.Dispose());

                        string outputDirectory = Path.GetDirectoryName(fastBuildOutputFile);

                        bffGenerator.ResolveEnvironmentVariables(conf.Platform,
                            new VariableAssignment("ProjectName", projectName),
                            new VariableAssignment("outputDirectory", outputDirectory));

                        subConfigIndex++;
                    }

                    if (configIndex == (configurationsToBuild.Count - 1) || configurationsToBuild[configIndex + 1].Platform != conf.Platform)
                    {
                        using (bffGenerator.Declare("fastBuildDefine", GetPlatformSpecificDefine(conf.Platform)))
                            bffGenerator.Write(Template.ConfigurationFile.PlatformEndSection);
                    }
                }

                bffGenerator.WriteTo(bffGeneratorProject);
                bffGenerator.Clear();
                ++configIndex;
            }

            foreach (string masterlessBff in confBffHasMasters.Where(x => !x.Value).Select(x => x.Key))
                Builder.Instance.LogWarningLine("Bff {0} doesn't appear in any master bff, it won't be buildable.", masterlessBff + FastBuildSettings.FastBuildConfigFileExtension);

            // Write all unity sections together at the beginning of the .bff just after the header.
            if (_unities.Any())
            {
                foreach (var unityFile in _unities.Keys.OrderBy(u => u.UnityName))
                {
                    using (bffWholeFileGenerator.Declare("unityFile", unityFile))
                        bffWholeFileGenerator.Write(Template.ConfigurationFile.UnitySection);

                    // Record the unities in the autocleanupdb to allow auto removal when they become stale.
                    // Note that can't record them as 'generated', since they are created by FastBuild and not by us.
                    int nbUnities = 1;
                    if (unityFile.UnityNumFiles != FileGeneratorUtilities.RemoveLineTag)
                    {
                        if (!int.TryParse(unityFile.UnityNumFiles, out nbUnities))
                            throw new Error("'{0}' cannot be converted to int!", unityFile.UnityNumFiles);
                    }

                    string outputPattern = unityFile.UnityOutputPattern == FileGeneratorUtilities.RemoveLineTag ? Sharpmake.Generators.FastBuild.Bff.Unity.DefaultUnityOutputPatternExtension : unityFile.UnityOutputPattern;
                    int wildcardIndex = outputPattern.IndexOf('*');
                    if (wildcardIndex == -1)
                        throw new Error("UnityOutputPattern must include a '*', but none was found in '{0}'!", unityFile.UnityNumFiles);

                    string firstStringChunk = outputPattern.Substring(0, wildcardIndex);
                    string lastStringChunk = outputPattern.Substring(wildcardIndex + 1);
                    for (int i = 1; i <= nbUnities; ++i)
                    {
                        string fullPath = Path.Combine(unityFile.UnityFullOutputPath, $"{firstStringChunk}{i}{lastStringChunk}");
                        Util.RecordInAutoCleanupDatabase(fullPath);
                    }
                }
            }

            // Now combine all the streams.
            bffGeneratorProject.WriteTo(bffWholeFileGenerator);

            // remove all line that contain RemoveLineTag
            bffWholeFileGenerator.RemoveTaggedLines();

            // Write bff file
            FileInfo bffFileInfo = new FileInfo(projectBffFile);

            if (builder.Context.WriteGeneratedFile(project.GetType(), bffFileInfo, bffWholeFileGenerator))
            {
                Project.IncrementFastBuildGeneratedFileCount();
                generatedFiles.Add(bffFileInfo.FullName);
            }
            else
            {
                Project.IncrementFastBuildUpToDateFileCount();
                skipFiles.Add(bffFileInfo.FullName);
            }
        }