Пример #1
0
        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
            }
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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 },
                });
            }
        }
Пример #4
0
        private static void RegisterPlatforms()
        {
            PlatformRegistry.Add(new Platform.x86.Architecture());
            PlatformRegistry.Add(new Platform.x64.Architecture());

            //PlatformRegistry.Add(new Platform.ARMv8A32.Architecture());
        }
Пример #5
0
        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;
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
                                            }
        }
Пример #9
0
        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);
        }
Пример #10
0
            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));
            }
Пример #11
0
 internal static bool IsSupportedFastBuildPlatform(this Platform platform)
 {
     return(PlatformRegistry.Has <IPlatformBff>(platform));
 }
Пример #12
0
        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);
            }
        }