private void GenerateConfOptions(GenerationContext context) { // generate all configuration options once... var projectOptionsGen = new ProjectOptionsGenerator(); var projectConfigurationOptions = new Dictionary <Project.Configuration, Options.ExplicitOptions>(); context.SetProjectConfigurationOptions(projectConfigurationOptions); foreach (Project.Configuration conf in context.ProjectConfigurations) { context.Configuration = conf; // set generator information var platformVcxproj = context.PresentPlatforms[conf.Platform]; var configurationTasks = PlatformRegistry.Get <Project.Configuration.IConfigurationTasks>(conf.Platform); conf.GeneratorSetGeneratedInformation( platformVcxproj.ExecutableFileExtension, platformVcxproj.PackageFileExtension, configurationTasks.GetDefaultOutputExtension(Project.Configuration.OutputType.Dll), platformVcxproj.ProgramDatabaseFileExtension); projectConfigurationOptions.Add(conf, new Options.ExplicitOptions()); context.CommandLineOptions = new ProjectOptionsGenerator.VcxprojCmdLineOptions(); projectOptionsGen.GenerateOptions(context); GenerateOptions(context); context.Reset(); // just a safety, not necessary to clean up } }
public void ResolveEnvironmentVariables(Platform platform, params VariableAssignment[] variables) { if (variables == null) { throw new ArgumentNullException(nameof(variables)); } var resolver = PlatformRegistry.Query <IPlatformDescriptor>(platform)?.GetPlatformEnvironmentResolver(variables); if (resolver != null) { Flush(); string content = ToString(); string cleanContent = resolver.Resolve(content); _stream.SetLength(0); // Logically the writer should be reusable on a modified stream after flushing it's // buffer but the API does not guarantee that buffered writers after modifying a stream. // So create a new string. _writer = new StreamWriter(_stream); _writer.Write(cleanContent); } }
private IEnumerable <IDictionary <string, string> > GetProjectEntries(Builder builder, Project project, Project.Configuration config) { var context = new CompileCommandGenerationContext(builder, project, config); var resolverParams = new[] { new VariableAssignment("project", context.Project), new VariableAssignment("target", context.Configuration.Target), new VariableAssignment("conf", context.Configuration) }; context.EnvironmentVariableResolver = PlatformRegistry.Get <IPlatformDescriptor>(config.Platform).GetPlatformEnvironmentResolver(resolverParams); var factory = new CompileCommandFactory(context); var database = project.GetSourceFilesForConfigurations(new[] { config }) .Except(config.ResolvedSourceFilesBuildExclude) .Where(f => project.SourceFilesCPPExtensions.Contains(Path.GetExtension(f))) .Select(factory.CreateCompileCommand); foreach (var cc in database) { CompileCommandGenerated?.Invoke(context, cc); yield return(new Dictionary <string, string> { { "directory", cc.Directory }, { "command", cc.Command }, { "file", cc.File }, }); } }
private static void RegisterPlatforms() { PlatformRegistry.Add(new Platform.x86.Architecture()); PlatformRegistry.Add(new Platform.x64.Architecture()); //PlatformRegistry.Add(new Platform.ARMv8A32.Architecture()); }
protected void Init() { bool debugLog = true; bool multithreaded = false; bool writeFiles = false; bool dumpDependency = true; DependencyTracker.GraphWriteLegend = false; Builder = new Builder( new BuildContext.GenerateAll(debugLog, writeFiles), multithreaded, dumpDependency, false, false, false, false, true, GetGeneratorsManager, null ); Builder.Arguments.ConfigureOrder = _configureOrder; // Force the test to load and register CommonPlatforms.dll as a Sharpmake extension // because sometimes you get the "no implementation of XX for platform YY." switch (_initType) { case InitType.Cpp: { // HACK: Explicitly reference something from CommonPlatforms to get // visual studio to load the assembly var platformWin64Type = typeof(Windows.Win64Platform); PlatformRegistry.RegisterExtensionAssembly(platformWin64Type.Assembly); } break; case InitType.CSharp: { var platformDotNetType = typeof(DotNetPlatform); PlatformRegistry.RegisterExtensionAssembly(platformDotNetType.Assembly); } break; default: throw new ArgumentOutOfRangeException(nameof(_initType), _initType, null); } Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); // Allow message log from builder. Builder.EventOutputError += (message, args) => { ++ErrorCount; Util.LogWrite(message, args); }; Builder.EventOutputWarning += (message, args) => { ++WarningCount; Util.LogWrite(message, args); }; Builder.EventOutputMessage += Util.LogWrite; Builder.EventOutputDebug += Util.LogWrite; }
private static int Main() { if (CommandLine.ContainParameter("breakintodebugger")) { System.Windows.Forms.MessageBox.Show("Debugger requested. Please attach a debugger and press OK"); Debugger.Break(); } // This GC gives a little bit better results than the other ones. "LowLatency" is giving really bad results(twice slower than the other ones). System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.SustainedLowLatency; Mutex oneInstanceMutex = null; Argument parameters = new Argument(); ExitCode exitCode = ExitCode.Success; try { DebugEnable = CommandLine.ContainParameter("verbose") || CommandLine.ContainParameter("debug") || CommandLine.ContainParameter("diagnostics"); Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; string versionString = string.Join(".", version.Major, version.Minor, version.Build); if (version.Revision != 0) { versionString += " (non-official)"; } LogWriteLine($"sharpmake {versionString}"); LogWriteLine(" arguments : {0}", CommandLine.GetProgramCommandLine()); LogWriteLine(" directory : {0}", Directory.GetCurrentDirectory()); LogWriteLine(string.Empty); // display help if wanted and quit if ((CommandLine.GetProgramCommandLine().Length == 0) || CommandLine.ContainParameter("help")) { LogWriteLine(CommandLine.GetCommandLineHelp(typeof(Argument), false)); return((int)ExitCode.Success); } AppDomain.CurrentDomain.AssemblyLoad += AppDomain_AssemblyLoad; // Log warnings and errors from builder Assembler.EventOutputError += ErrorWrite; Assembler.EventOutputWarning += WarningWrite; CommandLine.ExecuteOnObject(parameters); if (parameters.Exit) { return((int)ExitCode.Success); } const string sharpmakeSymbolPrefix = "_SHARPMAKE"; List <string> invalidSymbols = parameters.Defines.Where(define => define.StartsWith(sharpmakeSymbolPrefix)).ToList(); if (invalidSymbols.Any()) { string invalidSymbolsString = string.Join(", ", invalidSymbols); throw new Error($"Only Sharpmake process can define symbols starting with {sharpmakeSymbolPrefix}. Invalid symbols defined: {invalidSymbolsString}"); } parameters.Defines.Add($"{sharpmakeSymbolPrefix}_{version.Major}_{version.Minor}_X"); parameters.Defines.Add($"{sharpmakeSymbolPrefix}_{version.Major}_{version.Minor}_{version.Build}"); parameters.Validate(); // CommonPlatforms.dll is always loaded by default because those are shipped with // the Sharpmake package. PlatformRegistry.RegisterExtensionAssembly(typeof(Windows.Win32Platform).Assembly); // If any platform declares its own command line options, execute and validate // them as well. IEnumerable <Platform> platformsCmdLines = PlatformRegistry.GetAvailablePlatforms <ICommandLineInterface>(); foreach (var platform in platformsCmdLines) { var platformCmdLine = PlatformRegistry.Get <ICommandLineInterface>(platform); CommandLine.ExecuteOnObject(platformCmdLine); platformCmdLine.Validate(); } bool oneInstanceMutexCreated; string mutexName = string.Format("SharpmakeSingleInstanceMutex{0}", parameters.MutexSuffix); // Allow custom mutex name suffix. Useful to debug concurrently multiple sharpmake running from different branches oneInstanceMutex = new Mutex(true, mutexName, out oneInstanceMutexCreated); if (!oneInstanceMutexCreated) { try { if (!oneInstanceMutex.WaitOne(0)) { LogWriteLine("wait for another instance(s) of sharpmake to terminate..."); oneInstanceMutex.WaitOne(); } } catch (AbandonedMutexException) { // This occurs if another sharpmake is killed in the debugger } finally { LogWriteLine("waiting done."); } } switch (parameters.TestOption) { case TestOptions.Regression: { var regressionTest = new BuildContext.RegressionTest(parameters.OutputDirectory, parameters.ReferenceDirectory, parameters.RemapRoot); GenerateAll(regressionTest, parameters); exitCode = ExitCode.Success; var regressions = regressionTest.GetRegressions().ToList(); if (regressions.Count > 0) { exitCode = ExitCode.Error; DebugWriteLine($"{regressions.Count} Regressions detected:"); List <BuildContext.RegressionTest.OutputInfo> fileChanges = regressions.Where(x => x.FileStatus == BuildContext.RegressionTest.FileStatus.Different).ToList(); LogFileChanges(fileChanges, parameters.RegressionDiff); var fileMissing = regressions.Where(x => x.FileStatus == BuildContext.RegressionTest.FileStatus.NotGenerated).Select(x => x.ReferencePath).ToList(); if (fileMissing.Count > 0) { fileMissing.Sort(); DebugWriteLine($" {fileMissing.Count} files are missing from the output:"); fileMissing.ForEach(x => DebugWriteLine($" {x}")); } } } break; case TestOptions.QuickConfigure: { exitCode = AnalyzeConfigureOrder(parameters, true); } break; case TestOptions.Configure: { exitCode = AnalyzeConfigureOrder(parameters, false); } break; case TestOptions.None: default: { if (parameters.OutputDirectory != null) { // output redirect mode var redirectOutput = new BuildContext.RedirectOutput(parameters.OutputDirectory, parameters.RemapRoot); GenerateAll(redirectOutput, parameters); exitCode = ExitCode.Success; } else { var generateAll = new BuildContext.GenerateAll(parameters.DebugLog, parameters.WriteFiles); GenerateAll(generateAll, parameters); exitCode = ExitCode.Success; Util.ExecuteFilesAutoCleanup(); } } break; } if (CSproj.AllCsProjSubTypesInfos.Any()) { Util.SerializeAllCsprojSubTypes(CSproj.AllCsProjSubTypesInfos); } } catch (Error e) { // Log error message Exception innerException = e; while (innerException.InnerException != null) { innerException = innerException.InnerException; } ErrorWriteLine(Environment.NewLine + "Error:" + Environment.NewLine + innerException.Message); // Then log details LogWriteLine(Util.GetCompleteExceptionMessage(e, "\t")); exitCode = ExitCode.Error; } catch (InternalError e) { ErrorWriteLine(Environment.NewLine + "Internal Error:"); LogWriteLine(Util.GetCompleteExceptionMessage(e, "\t")); exitCode = ExitCode.InternalError; } #if !DEBUG // Use this to catch right away if an exception throw catch (Exception e) { LogWriteLine(Environment.NewLine + "Exception Error:"); LogWriteLine(Util.GetCompleteExceptionMessage(e, "\t")); exitCode = ExitCode.UnknownError; } #endif finally { if (oneInstanceMutex != null) { oneInstanceMutex.ReleaseMutex(); GC.KeepAlive(oneInstanceMutex); } if (parameters.Debug) { Console.WriteLine("DEBUG Sharpmake.Application: Press any key to exit..."); Console.ReadKey(); } } LogWriteLine(@"{0} errors, {1} warnings", s_errorCount, s_warningCount); if (s_errorCount != 0) { if (Debugger.IsAttached) { LogWriteLine("Please look at the errors."); Debugger.Break(); } } // returning exit code and error count separately because they can result in an exit code of 0 if they are added together. if (s_errorCount != 0) { return(s_errorCount); } return((int)exitCode); }
public void Init() { bool debugLog = true; bool multithreaded = false; bool writeFiles = false; bool dumpDependency = true; DependencyTracker.GraphWriteLegend = false; Builder = new Builder( new Sharpmake.BuildContext.GenerateAll(debugLog, writeFiles), multithreaded, dumpDependency, false, false, false, false, GetGeneratorsManager ); // Force the test to load and register CommonPlatforms.dll as a Sharpmake extension // because sometimes you get the "no implementation of XX for platform YY." var platformDotNetType = typeof(DotNetPlatform); PlatformRegistry.RegisterExtensionAssembly(platformDotNetType.Assembly); Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); // Allow message log from builder. Builder.OutputDelegate log = (msg, args) => { Console.Write(msg, args); if (System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Trace.Write(string.Format(msg, args)); } }; Builder.EventOutputError += log; Builder.EventOutputWarning += log; Builder.EventOutputMessage += log; Builder.EventOutputDebug += log; //////////////////////////////////////////////////////////////////// // Register projects to generate here var sharpmakeProjects = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && t.Namespace == _namespace); // Also create some random source files Util.FakePathPrefix = Directory.GetCurrentDirectory(); foreach (var sharpmakeProject in sharpmakeProjects) { Util.AddNewFakeFile(Util.PathMakeStandard(Path.Combine(sharpmakeProject.Name, sharpmakeProject.Name + "_source.cs")), 0); } foreach (var sharpmakeProject in sharpmakeProjects) { Builder.Arguments.Generate(sharpmakeProject); } //////////////////////////////////////////////////////////////////// Builder.BuildProjectAndSolution(); var outputs = Builder.Generate(); if (dumpDependency) { DependencyTracker.Instance.DumpGraphs(outputs); } }
private static void WriteMasterSettingsSection(FileGenerator masterBffGenerator, MasterBffInfo masterBffInfo) { string tempFolder = Path.GetTempPath(); string cachePath = FileGeneratorUtilities.RemoveLineTag; string cachePluginDLL = FileGeneratorUtilities.RemoveLineTag; string workerConnectionLimit = FileGeneratorUtilities.RemoveLineTag; if (FastBuildSettings.CachePath != null) { cachePath = ".CachePath = '" + FastBuildSettings.CachePath + "'"; if (FastBuildSettings.CachePluginDLLFilePath != null) { cachePluginDLL = ".CachePluginDLL = '" + FastBuildSettings.CachePluginDLLFilePath + "'"; } } if (FastBuildSettings.FastBuildWorkerConnectionLimit >= 0) { workerConnectionLimit = ".WorkerConnectionLimit = " + FastBuildSettings.FastBuildWorkerConnectionLimit.ToString(); } string fastBuildPATH = FileGeneratorUtilities.RemoveLineTag; if (FastBuildSettings.SetPathToResourceCompilerInEnvironment) { // !FIX FOR LINK : fatal error LNK1158: cannot run rc.exe! // // link.exe on win64 executes rc.exe by itself on some occasions // if it doesn't find it, link errors can occur // // link.exe will first search rc.exe next to it, and if it fails // it will look for it in the folders listed by the PATH // environment variable, so we'll try to replicate that process // in sharpmake: // // 1) Get the linker path // 2) Look for rc.exe near it // 3) If found, exit // 4) If not, add a PATH environment variable pointing to the rc.exe folder List <Platform> microsoftPlatforms = PlatformRegistry.GetAvailablePlatforms <IMicrosoftPlatformBff>().ToList(); var resourceCompilerPaths = new Strings(); foreach (CompilerSettings setting in masterBffInfo.CompilerSettings.Values) { if (!microsoftPlatforms.Any(x => setting.PlatformFlags.HasFlag(x))) { continue; } string defaultResourceCompilerPath = Path.GetDirectoryName(setting.DevEnv.GetWindowsResourceCompiler(Platform.win64)); foreach (var configurationPair in setting.Configurations) { var configuration = configurationPair.Value; // check if the configuration has a linker if (configuration.LinkerPath != FileGeneratorUtilities.RemoveLineTag) { // if so, try to find a rc.exe near it if (!File.Exists(Path.Combine(configuration.LinkerPath, "rc.exe"))) { // if not found, get the folder of the custom // rc.exe or the default one to add it to PATH if (configuration.ResourceCompiler != FileGeneratorUtilities.RemoveLineTag) { resourceCompilerPaths.Add(Path.GetDirectoryName(configuration.ResourceCompiler)); } else { resourceCompilerPaths.Add(defaultResourceCompilerPath); } } } } } if (resourceCompilerPaths.Count == 1) { fastBuildPATH = Util.GetCapitalizedPath(resourceCompilerPaths.First()); } else if (resourceCompilerPaths.Count > 1) { throw new Error("Multiple conflicting resource compilers found in PATH! Please verify your ResourceCompiler settings."); } } using (masterBffGenerator.Declare("fastBuildProjectName", "Master")) using (masterBffGenerator.Declare("fastBuildTempFolder", tempFolder)) using (masterBffGenerator.Declare("CachePath", cachePath)) using (masterBffGenerator.Declare("CachePluginDLL", cachePluginDLL)) using (masterBffGenerator.Declare("WorkerConnectionLimit", workerConnectionLimit)) using (masterBffGenerator.Declare("fastBuildSystemRoot", FastBuildSettings.SystemRoot)) using (masterBffGenerator.Declare("fastBuildUserProfile", Environment.GetFolderPath(Environment.SpecialFolder.UserProfile))) using (masterBffGenerator.Declare("fastBuildPATH", fastBuildPATH)) using (masterBffGenerator.Declare("fastBuildAllowDBMigration", FastBuildSettings.FastBuildAllowDBMigration ? "true" : FileGeneratorUtilities.RemoveLineTag)) { masterBffGenerator.Write(Bff.Template.ConfigurationFile.HeaderFile); masterBffGenerator.Write(Bff.Template.ConfigurationFile.GlobalSettings); } }
private static bool GenerateMasterBffFile(Builder builder, ConfigurationsPerBff configurationsPerBff) { string masterBffFilePath = Util.GetCapitalizedPath(configurationsPerBff.BffFilePathWithExtension); string masterBffDirectory = Path.GetDirectoryName(masterBffFilePath); string masterBffFileName = Path.GetFileName(masterBffFilePath); // Global configuration file is in the same directory as the master bff but filename suffix added to its filename. string globalConfigFullPath = GetGlobalBffConfigFileName(masterBffFilePath); string globalConfigFileName = Path.GetFileName(globalConfigFullPath); var solutionProjects = configurationsPerBff.ResolvedProjects; if (solutionProjects.Count == 0 && configurationsPerBff.ProjectsWereFiltered) { // We are running in filter mode for submit assistant and all projects were filtered out. // We need to skip generation and delete any existing master bff file. Util.TryDeleteFile(masterBffFilePath); return(false); } // Start writing Bff var fileGenerator = new FileGenerator(); var masterBffInfo = new MasterBffInfo(); var bffPreBuildSection = new Dictionary <string, string>(); var bffCustomPreBuildSection = new Dictionary <string, string>(); var bffMasterSection = new Dictionary <string, string>(); var masterBffCopySections = new List <string>(); var masterBffCustomSections = new UniqueList <string>(); // section that is not ordered bool mustGenerateFastbuild = false; var platformBffCache = new Dictionary <Platform, IPlatformBff>(); var verificationPostBuildCopies = new Dictionary <string, string>(); foreach (Solution.Configuration solutionConfiguration in configurationsPerBff) { foreach (var solutionProject in solutionProjects) { var project = solutionProject.Project; // Export projects do not have any bff if (project.GetType().IsDefined(typeof(Export), false)) { continue; } // When the project has a source file filter, only keep it if the file list is not empty if (project.SourceFilesFilters != null && (project.SourceFilesFiltersCount == 0 || project.SkipProjectWhenFiltersActive)) { continue; } Solution.Configuration.IncludedProjectInfo includedProject = solutionConfiguration.GetProject(solutionProject.Project.GetType()); bool perfectMatch = includedProject != null && solutionProject.Configurations.Contains(includedProject.Configuration); if (!perfectMatch) { continue; } var conf = includedProject.Configuration; if (!conf.IsFastBuildEnabledProjectConfig()) { continue; } mustGenerateFastbuild = true; IPlatformBff platformBff = platformBffCache.GetValueOrAdd(conf.Platform, PlatformRegistry.Query <IPlatformBff>(conf.Platform)); platformBff.AddCompilerSettings(masterBffInfo.CompilerSettings, conf); if (FastBuildSettings.WriteAllConfigsSection && includedProject.ToBuild == Solution.Configuration.IncludedProjectInfo.Build.Yes) { masterBffInfo.AllConfigsSections.Add(Bff.GetShortProjectName(project, conf)); } using (fileGenerator.Declare("conf", conf)) using (fileGenerator.Declare("target", conf.Target)) using (fileGenerator.Declare("project", conf.Project)) { var preBuildEvents = new Dictionary <string, Project.Configuration.BuildStepBase>(); if (conf.Output == Project.Configuration.OutputType.Exe || conf.ExecuteTargetCopy) { var copies = ProjectOptionsGenerator.ConvertPostBuildCopiesToRelative(conf, masterBffDirectory); foreach (var copy in copies) { var sourceFile = copy.Key; var sourceFileName = Path.GetFileName(sourceFile); var destinationFolder = copy.Value; var destinationFile = Path.Combine(destinationFolder, sourceFileName); // 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(masterBffDirectory, destinationFolder, conf.Project.RootPath, true, conf.Project.RootPath); { string key = sourceFileName + destinationRelativeToGlobal; string currentSourceFullPath = Util.PathGetAbsolute(masterBffDirectory, sourceFile); string previous; if (verificationPostBuildCopies.TryGetValue(key, out previous)) { if (previous != currentSourceFullPath) { builder.LogErrorLine("A post-build copy to the destination '{0}' already exist but from different sources: '{1}' and '{2}'!", Util.PathGetAbsolute(masterBffDirectory, destinationFolder), previous, currentSourceFullPath); } } else { verificationPostBuildCopies.Add(key, currentSourceFullPath); } } string fastBuildCopyAlias = UtilityMethods.GetFastBuildCopyAlias(sourceFileName, destinationRelativeToGlobal); { using (fileGenerator.Declare("fastBuildCopyAlias", fastBuildCopyAlias)) using (fileGenerator.Declare("fastBuildCopySource", sourceFile)) using (fileGenerator.Declare("fastBuildCopyDest", destinationFile)) { if (!bffMasterSection.ContainsKey(fastBuildCopyAlias)) { bffMasterSection.Add(fastBuildCopyAlias, fileGenerator.Resolver.Resolve(Bff.Template.ConfigurationFile.CopyFileSection)); } } } } foreach (var eventPair in conf.EventPreBuildExecute) { preBuildEvents.Add(eventPair.Key, eventPair.Value); } foreach (var buildEvent in conf.ResolvedEventPreBuildExe) { string eventKey = ProjectOptionsGenerator.MakeBuildStepName(conf, buildEvent, Vcxproj.BuildStep.PreBuild); preBuildEvents.Add(eventKey, buildEvent); } WriteEvents(fileGenerator, preBuildEvents, bffPreBuildSection, masterBffDirectory); } var customPreBuildEvents = new Dictionary <string, Project.Configuration.BuildStepBase>(); foreach (var eventPair in conf.EventCustomPrebuildExecute) { customPreBuildEvents.Add(eventPair.Key, eventPair.Value); } foreach (var buildEvent in conf.ResolvedEventCustomPreBuildExe) { string eventKey = ProjectOptionsGenerator.MakeBuildStepName(conf, buildEvent, Vcxproj.BuildStep.PreBuildCustomAction); customPreBuildEvents.Add(eventKey, buildEvent); } WriteEvents(fileGenerator, customPreBuildEvents, bffCustomPreBuildSection, masterBffDirectory); if (includedProject.ToBuild == Solution.Configuration.IncludedProjectInfo.Build.Yes) { MergeBffIncludeTreeRecursive(conf, ref masterBffInfo.BffIncludeToDependencyIncludes); } } } } if (!mustGenerateFastbuild) { throw new Error("Sharpmake-FastBuild : Trying to generate a MasterBff with none of its projects having a FastBuild configuration, or having a platform supporting it, or all of them having conf.DoNotGenerateFastBuild = true"); } masterBffCopySections.AddRange(bffMasterSection.Values); masterBffCopySections.AddRange(bffPreBuildSection.Values); masterBffCustomSections.AddRange(bffCustomPreBuildSection.Values); var result = new StringBuilder(); foreach (var projectBffFullPath in GetMasterIncludeList(masterBffInfo.BffIncludeToDependencyIncludes)) { string projectFullPath = Path.GetDirectoryName(projectBffFullPath); var projectPathRelativeFromMasterBff = Util.PathGetRelative(masterBffDirectory, projectFullPath, true); string bffKeyRelative = Path.Combine(Bff.CurrentBffPathKey, Path.GetFileName(projectBffFullPath)); string include = string.Join( Environment.NewLine, "{", $" {Bff.CurrentBffPathVariable} = \"{projectPathRelativeFromMasterBff}\"", $" #include \"{bffKeyRelative}\"", "}" ); result.AppendLine(include); } string fastBuildMasterBffDependencies = result.Length == 0 ? FileGeneratorUtilities.RemoveLineTag : result.ToString(); GenerateMasterBffGlobalSettingsFile(builder, globalConfigFullPath, masterBffInfo); using (fileGenerator.Declare("fastBuildProjectName", masterBffFileName)) using (fileGenerator.Declare("fastBuildGlobalConfigurationInclude", $"#include \"{globalConfigFileName}\"")) { fileGenerator.Write(Bff.Template.ConfigurationFile.HeaderFile); foreach (Platform platform in platformBffCache.Keys) // kind of cheating to use that cache instead of the masterBffInfo.CompilerSettings, but it works :) { using (fileGenerator.Declare("fastBuildDefine", Bff.GetPlatformSpecificDefine(platform))) fileGenerator.Write(Bff.Template.ConfigurationFile.Define); } fileGenerator.Write(Bff.Template.ConfigurationFile.GlobalConfigurationInclude); } WriteMasterCopySection(fileGenerator, masterBffCopySections); WriteMasterCustomSection(fileGenerator, masterBffCustomSections); using (fileGenerator.Declare("fastBuildProjectName", masterBffFileName)) using (fileGenerator.Declare("fastBuildOrderedBffDependencies", fastBuildMasterBffDependencies)) { fileGenerator.Write(Bff.Template.ConfigurationFile.Includes); } if (masterBffInfo.AllConfigsSections.Count != 0) { using (fileGenerator.Declare("fastBuildConfigs", UtilityMethods.FBuildFormatList(masterBffInfo.AllConfigsSections, 4))) { fileGenerator.Write(Bff.Template.ConfigurationFile.AllConfigsSection); } } // remove all line that contain RemoveLineTag fileGenerator.RemoveTaggedLines(); MemoryStream bffCleanMemoryStream = fileGenerator.ToMemoryStream(); // Write master .bff file FileInfo bffFileInfo = new FileInfo(masterBffFilePath); bool updated = builder.Context.WriteGeneratedFile(null, bffFileInfo, bffCleanMemoryStream); foreach (var confsPerSolution in configurationsPerBff) { confsPerSolution.Solution.PostGenerationCallback?.Invoke(masterBffDirectory, Path.GetFileNameWithoutExtension(masterBffFileName), FastBuildSettings.FastBuildConfigFileExtension); } return(updated); }
public GenerationContext(Builder builder, string projectPath, Project project, IEnumerable <Project.Configuration> projectConfigurations) { Builder = builder; FileInfo fileInfo = new FileInfo(projectPath); ProjectPath = fileInfo.FullName; ProjectDirectory = Path.GetDirectoryName(ProjectPath); ProjectFileName = Path.GetFileName(ProjectPath); Project = project; AndroidPackageProject = (AndroidPackageProject)Project; ProjectDirectoryCapitalized = Util.GetCapitalizedPath(ProjectDirectory); ProjectSourceCapitalized = Util.GetCapitalizedPath(Project.SourceRootPath); ProjectConfigurations = VsUtil.SortConfigurations(projectConfigurations, Path.Combine(ProjectDirectoryCapitalized, ProjectFileName + ProjectExtension)).ToArray(); DevelopmentEnvironmentsRange = new DevEnvRange(ProjectConfigurations); PresentPlatforms = ProjectConfigurations.Select(conf => conf.Platform).Distinct().ToDictionary(p => p, p => PlatformRegistry.Get <IPlatformVcxproj>(p)); }
internal static bool IsSupportedFastBuildPlatform(this Platform platform) { return(PlatformRegistry.Has <IPlatformBff>(platform)); }
private void FillIncludeDirectoriesOptions(CompileCommandGenerationContext context) { // TODO: really not ideal, refactor and move the properties we need from it someplace else var platformVcxproj = PlatformRegistry.Query <IPlatformVcxproj>(context.Configuration.Platform); var includePaths = new OrderableStrings(platformVcxproj.GetIncludePaths(context)); var resourceIncludePaths = new OrderableStrings(platformVcxproj.GetResourceIncludePaths(context)); context.CommandLineOptions["AdditionalIncludeDirectories"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["AdditionalResourceIncludeDirectories"] = FileGeneratorUtilities.RemoveLineTag; context.CommandLineOptions["AdditionalUsingDirectories"] = FileGeneratorUtilities.RemoveLineTag; var platformDescriptor = PlatformRegistry.Get <IPlatformDescriptor>(context.Configuration.Platform); string defaultCmdLineIncludePrefix = _flags[CompilerFlags.IncludePath]; // Fill include dirs var dirs = new List <string>(); var platformIncludePaths = platformVcxproj.GetPlatformIncludePathsWithPrefix(context); var platformIncludePathsPrefixed = platformIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p.Path, p.CmdLinePrefix)).ToList(); dirs.AddRange(platformIncludePathsPrefixed); // TODO: move back up, just below the creation of the dirs list dirs.AddRange(includePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p, defaultCmdLineIncludePrefix))); if (dirs.Any()) { context.CommandLineOptions["AdditionalIncludeDirectories"] = string.Join(" ", dirs); _arguments.AddRange(dirs); } // Fill resource include dirs var resourceDirs = new List <string>(); resourceDirs.AddRange(resourceIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p, defaultCmdLineIncludePrefix))); if (Options.GetObject <Options.Vc.General.PlatformToolset>(context.Configuration).IsLLVMToolchain() && Options.GetObject <Options.Vc.LLVM.UseClangCl>(context.Configuration) == Options.Vc.LLVM.UseClangCl.Enable) { // with LLVM as toolchain, we are still using the default resource compiler, so we need the default include prefix // TODO: this is not great, ideally we would need the prefix to be per "compiler", and a platform can have many var platformIncludePathsDefaultPrefix = platformIncludePaths.Select(p => CmdLineConvertIncludePathsFunc(context, p.Path, defaultCmdLineIncludePrefix)); resourceDirs.AddRange(platformIncludePathsDefaultPrefix); } else { resourceDirs.AddRange(platformIncludePathsPrefixed); } if (resourceDirs.Any()) { context.CommandLineOptions["AdditionalResourceIncludeDirectories"] = string.Join(" ", resourceDirs); _arguments.AddRange(resourceDirs); } // Fill using dirs Strings additionalUsingDirectories = Options.GetStrings <Options.Vc.Compiler.AdditionalUsingDirectories>(context.Configuration); additionalUsingDirectories.AddRange(context.Configuration.AdditionalUsingDirectories); additionalUsingDirectories.AddRange(platformVcxproj.GetCxUsingPath(context)); if (additionalUsingDirectories.Any()) { var cmdAdditionalUsingDirectories = additionalUsingDirectories.Select(p => CmdLineConvertIncludePathsFunc(context, p, "/AI")); context.CommandLineOptions["AdditionalUsingDirectories"] = string.Join(" ", cmdAdditionalUsingDirectories); _arguments.AddRange(cmdAdditionalUsingDirectories); } }