Example #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
            }
        }
Example #2
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 },
                });
            }
        }
Example #3
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);
        }
Example #4
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));
            }
Example #5
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);
            }
        }