Exemple #1
0
        public static void Main()
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            EditorPath.EditorTitle = XenkoGameStudio.EditorName;

            if (IntPtr.Size == 4)
            {
                MessageBox.Show("Xenko GameStudio requires a 64bit OS to run.", "Xenko", MessageBoxButton.OK, MessageBoxImage.Error);
                Environment.Exit(1);
            }

            PrivacyPolicyHelper.RestartApplication = RestartApplication;
            PrivacyPolicyHelper.EnsurePrivacyPolicyXenko30();

            // We use MRU of the current version only when we're trying to reload last session.
            var mru = new MostRecentlyUsedFileCollection(InternalSettings.LoadProfileCopy, InternalSettings.MostRecentlyUsedSessions, InternalSettings.WriteFile);

            mru.LoadFromSettings();

            EditorSettings.Initialize();
            Thread.CurrentThread.Name = "Main thread";

            // Install Metrics for the editor
            using (XenkoGameStudio.MetricsClient = new MetricsClient(CommonApps.XenkoEditorAppId))
            {
                try
                {
                    // Environment.GetCommandLineArgs correctly process arguments regarding the presence of '\' and '"'
                    var args = Environment.GetCommandLineArgs().Skip(1).ToList();
                    var startupSessionPath = XenkoEditorSettings.StartupSession.GetValue();
                    var lastSessionPath    = EditorSettings.ReloadLastSession.GetValue() ? mru.MostRecentlyUsedFiles.FirstOrDefault() : null;
                    var initialSessionPath = !UPath.IsNullOrEmpty(startupSessionPath) ? startupSessionPath : lastSessionPath?.FilePath;

                    // Handle arguments
                    for (var i = 0; i < args.Count; i++)
                    {
                        if (args[i] == "/LauncherWindowHandle")
                        {
                            windowHandle = new IntPtr(long.Parse(args[++i]));
                        }
                        else if (args[i] == "/NewProject")
                        {
                            initialSessionPath = null;
                        }
                        else if (args[i] == "/DebugEditorGraphics")
                        {
                            EmbeddedGame.DebugMode = true;
                        }
                        else if (args[i] == "/RenderDoc")
                        {
                            // TODO: RenderDoc is not working here (when not in debug)
                            GameStudioPreviewService.DisablePreview = true;
                            renderDocManager = new RenderDocManager();
                        }
                        else if (args[i] == "/Reattach")
                        {
                            var debuggerProcessId = int.Parse(args[++i]);

                            if (!System.Diagnostics.Debugger.IsAttached)
                            {
                                using (var debugger = VisualStudioDebugger.GetByProcess(debuggerProcessId))
                                {
                                    debugger?.Attach();
                                }
                            }
                        }
                        else if (args[i] == "/RecordEffects")
                        {
                            GameStudioBuilderService.GlobalEffectLogPath = args[++i];
                        }
                        else
                        {
                            initialSessionPath = args[i];
                        }
                    }
                    RuntimeHelpers.RunModuleConstructor(typeof(Asset).Module.ModuleHandle);

                    //listen to logger for crash report
                    GlobalLogger.GlobalMessageLogged += GlobalLoggerOnGlobalMessageLogged;

                    mainDispatcher = Dispatcher.CurrentDispatcher;
                    mainDispatcher.InvokeAsync(() => Startup(initialSessionPath));

                    using (new WindowManager(mainDispatcher))
                    {
                        app = new App {
                            ShutdownMode = ShutdownMode.OnExplicitShutdown
                        };
                        app.Activated += (sender, eventArgs) =>
                        {
                            XenkoGameStudio.MetricsClient?.SetActiveState(true);
                        };
                        app.Deactivated += (sender, eventArgs) =>
                        {
                            XenkoGameStudio.MetricsClient?.SetActiveState(false);
                        };

                        app.InitializeComponent();
                        app.Run();
                    }

                    renderDocManager?.Shutdown();
                }
                catch (Exception e)
                {
                    HandleException(e, 0);
                }
            }
        }
Exemple #2
0
        public int Run(string[] args)
        {
            // This is used by ExecServer to retrieve the logs directly without using the console redirect (which is not working well
            // in a multi-domain scenario)
            var redirectLogToAppDomainAction = AppDomain.CurrentDomain.GetData("AppDomainLogToAction") as Action <string, ConsoleColor>;

            clock = Stopwatch.StartNew();

            // TODO this is hardcoded. Check how to make this dynamic instead.
            RuntimeHelpers.RunModuleConstructor(typeof(IProceduralModel).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(MaterialKeys).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(SpriteFontAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(ModelAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(SpriteStudioAnimationAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(ParticleSystem).Module.ModuleHandle);
            //var project = new Package();
            //project.Save("test.xkpkg");

            //Thread.Sleep(10000);
            //var spriteFontAsset = StaticFontAsset.New();
            //Content.Save("test.xkfnt", spriteFontAsset);
            //project.Refresh();

            //args = new string[] { "test.xkpkg", "-o:app_data", "-b:tmp", "-t:1" };

            var exeName           = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
            var showHelp          = false;
            var buildEngineLogger = GlobalLogger.GetLogger("BuildEngine");
            var options           = new PackageBuilderOptions(new ForwardingLoggerResult(buildEngineLogger));

            var p = new OptionSet
            {
                "Copyright (C) 2011-2014 Silicon Studio Corporation. All Rights Reserved",
                "Xenko Build Tool - Version: "
                +
                String.Format(
                    "{0}.{1}.{2}",
                    typeof(Program).Assembly.GetName().Version.Major,
                    typeof(Program).Assembly.GetName().Version.Minor,
                    typeof(Program).Assembly.GetName().Version.Build) + string.Empty,
                string.Format("Usage: {0} inputPackageFile [options]* -b buildPath", exeName),
                string.Empty,
                "=== Options ===",
                string.Empty,
                { "h|help", "Show this message and exit", v => showHelp = v != null },
                { "v|verbose", "Show more verbose progress logs", v => options.Verbose = v != null },
                { "d|debug", "Show debug logs (imply verbose)", v => options.Debug = v != null },
                { "log", "Enable file logging", v => options.EnableFileLogging = v != null },
                { "disable-auto-compile", "Disable auto-compile of projects", v => options.DisableAutoCompileProjects = v != null },
                { "p|profile=", "Profile name", v => options.BuildProfile = v },
                { "project-configuration=", "Project configuration", v => options.ProjectConfiguration = v },
                { "platform=", "Platform name", v => options.Platform = (PlatformType)Enum.Parse(typeof(PlatformType), v) },
                { "graphics-platform=", "Graphics Platform name", v => options.GraphicsPlatform = (GraphicsPlatform)Enum.Parse(typeof(GraphicsPlatform), v) },
                { "get-graphics-platform", "Get Graphics Platform name (needs a xkpkg and a profile)", v => options.GetGraphicsPlatform = v != null },
                { "solution-file=", "Solution File Name", v => options.SolutionFile = v },
                { "package-id=", "Package Id from the solution file", v => options.PackageId = Guid.Parse(v) },
                { "package-file=", "Input Package File Name", v => options.PackageFile = v },
                { "o|output-path=", "Output path", v => options.OutputDirectory = v },
                { "b|build-path=", "Build path", v => options.BuildDirectory = v },
                { "log-file=", "Log build in a custom file.", v =>
                  {
                      options.EnableFileLogging = v != null;
                      options.CustomLogFileName = v;
                  } },
                { "log-pipe=", "Log pipe.", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          options.LogPipeNames.Add(v);
                      }
                  } },
                { "monitor-pipe=", "Monitor pipe.", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          options.MonitorPipeNames.Add(v);
                      }
                  } },
                { "slave=", "Slave pipe", v => options.SlavePipe = v }, // Benlitz: I don't think this should be documented
                { "server=", "This Compiler is launched as a server", v => { } },
                { "t|threads=", "Number of threads to create. Default value is the number of hardware threads available.", v => options.ThreadCount = int.Parse(v) },
                { "test=", "Run a test session.", v => options.TestName = v },
                { "property:", "Properties. Format is name1=value1;name2=value2", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              var equalIndex = nameValue.IndexOf('=');
                              if (equalIndex == -1)
                              {
                                  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
                              }

                              options.Properties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
                          }
                      }
                  } },
                { "compile-property:", "Compile properties. Format is name1=value1;name2=value2", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          if (options.ExtraCompileProperties == null)
                          {
                              options.ExtraCompileProperties = new Dictionary <string, string>();
                          }

                          foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              var equalIndex = nameValue.IndexOf('=');
                              if (equalIndex == -1)
                              {
                                  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
                              }

                              options.ExtraCompileProperties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
                          }
                      }
                  } },
                {
                    "reattach-debugger=", "Reattach to a Visual Studio debugger", v =>
                    {
                        int debuggerProcessId;
                        if (!string.IsNullOrEmpty(v) && int.TryParse(v, out debuggerProcessId))
                        {
                            if (!Debugger.IsAttached)
                            {
                                using (var debugger = VisualStudioDebugger.GetByProcess(debuggerProcessId))
                                {
                                    debugger?.Attach();
                                }
                            }
                        }
                    }
                },
            };

            TextWriterLogListener fileLogListener = null;

            BuildResultCode exitCode;

            RemoteLogForwarder assetLogger = null;

            try
            {
                var unexpectedArgs = p.Parse(args);

                // Set remote logger
                assetLogger = new RemoteLogForwarder(options.Logger, options.LogPipeNames);
                GlobalLogger.GlobalMessageLogged += assetLogger;

                // Activate proper log level
                buildEngineLogger.ActivateLog(options.LoggerType);

                // Output logs to the console with colored messages
                if (options.SlavePipe == null && !options.LogPipeNames.Any())
                {
                    if (redirectLogToAppDomainAction != null)
                    {
                        globalLoggerOnGlobalMessageLogged = new LogListenerRedirectToAction(redirectLogToAppDomainAction);
                    }
                    else
                    {
                        globalLoggerOnGlobalMessageLogged = new ConsoleLogListener {
                            LogMode = ConsoleLogMode.Always
                        };
                    }
                    globalLoggerOnGlobalMessageLogged.TextFormatter = FormatLog;
                    GlobalLogger.GlobalMessageLogged += globalLoggerOnGlobalMessageLogged;
                }

                if (unexpectedArgs.Any())
                {
                    throw new OptionException("Unexpected arguments [{0}]".ToFormat(string.Join(", ", unexpectedArgs)), "args");
                }
                try
                {
                    options.ValidateOptions();
                }
                catch (ArgumentException ex)
                {
                    throw new OptionException(ex.Message, ex.ParamName);
                }

                // Also write logs from master process into a file
                if (options.SlavePipe == null)
                {
                    if (options.EnableFileLogging)
                    {
                        string logFileName = options.CustomLogFileName;
                        if (string.IsNullOrEmpty(logFileName))
                        {
                            string inputName = Path.GetFileNameWithoutExtension(options.PackageFile);
                            logFileName = "Logs/Build-" + inputName + "-" + DateTime.Now.ToString("yy-MM-dd-HH-mm") + ".txt";
                        }

                        string dirName = Path.GetDirectoryName(logFileName);
                        if (dirName != null)
                        {
                            Directory.CreateDirectory(dirName);
                        }

                        fileLogListener = new TextWriterLogListener(new FileStream(logFileName, FileMode.Create))
                        {
                            TextFormatter = FormatLog
                        };
                        GlobalLogger.GlobalMessageLogged += fileLogListener;
                    }
                    if (!options.GetGraphicsPlatform)
                    {
                        options.Logger.Info("BuildEngine arguments: " + string.Join(" ", args));
                        options.Logger.Info("Starting builder.");
                    }
                }
                else
                {
                    IsSlave = true;
                }

                if (showHelp)
                {
                    p.WriteOptionDescriptions(Console.Out);
                    exitCode = BuildResultCode.Successful;
                }
                else if (!string.IsNullOrEmpty(options.TestName))
                {
                    var test = new TestSession();
                    test.RunTest(options.TestName, options.Logger);
                    exitCode = BuildResultCode.Successful;
                }
                else
                {
                    builder = new PackageBuilder(options);
                    if (!IsSlave && redirectLogToAppDomainAction == null)
                    {
                        Console.CancelKeyPress += OnConsoleOnCancelKeyPress;
                    }
                    exitCode = builder.Build();
                }
            }
            catch (OptionException e)
            {
                options.Logger.Error($"Command option '{e.OptionName}': {e.Message}");
                exitCode = BuildResultCode.CommandLineError;
            }
            catch (Exception e)
            {
                options.Logger.Error($"Unhandled exception", e);
                exitCode = BuildResultCode.BuildError;
            }
            finally
            {
                // Flush and close remote logger
                if (assetLogger != null)
                {
                    GlobalLogger.GlobalMessageLogged -= assetLogger;
                    assetLogger.Dispose();
                }

                if (fileLogListener != null)
                {
                    GlobalLogger.GlobalMessageLogged -= fileLogListener;
                    fileLogListener.LogWriter.Close();
                }

                // Output logs to the console with colored messages
                if (globalLoggerOnGlobalMessageLogged != null)
                {
                    GlobalLogger.GlobalMessageLogged -= globalLoggerOnGlobalMessageLogged;
                }
                if (builder != null && !IsSlave && redirectLogToAppDomainAction == null)
                {
                    Console.CancelKeyPress -= OnConsoleOnCancelKeyPress;
                }

                // Make sure that MSBuild doesn't hold anything else
                VSProjectHelper.Reset();

                // Reset cache hold by YamlSerializer
                YamlSerializer.Default.ResetCache();
            }
            return((int)exitCode);
        }
Exemple #3
0
 static TexturePackerTests()
 {
     RuntimeHelpers.RunModuleConstructor(typeof(Asset).Module.ModuleHandle);
 }
Exemple #4
0
        public int Run(string[] args)
        {
            // This is used by ExecServer to retrieve the logs directly without using the console redirect (which is not working well
            // in a multi-domain scenario)
            var redirectLogToAppDomainAction = AppDomain.CurrentDomain.GetData("AppDomainLogToAction") as Action <string, ConsoleColor>;

            clock = Stopwatch.StartNew();

            // TODO this is hardcoded. Check how to make this dynamic instead.
            RuntimeHelpers.RunModuleConstructor(typeof(IProceduralModel).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(MaterialKeys).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(SpriteFontAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(ModelAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(SpriteStudioAnimationAsset).Module.ModuleHandle);
            RuntimeHelpers.RunModuleConstructor(typeof(ParticleSystem).Module.ModuleHandle);
            //var project = new Package();
            //project.Save("test.xkpkg");

            //Thread.Sleep(10000);
            //var spriteFontAsset = StaticFontAsset.New();
            //Content.Save("test.xkfnt", spriteFontAsset);
            //project.Refresh();

            //args = new string[] { "test.xkpkg", "-o:app_data", "-b:tmp", "-t:1" };

            var exeName           = Path.GetFileName(Assembly.GetExecutingAssembly().Location);
            var showHelp          = false;
            var packMode          = false;
            var buildEngineLogger = GlobalLogger.GetLogger("BuildEngine");
            var options           = new PackageBuilderOptions(new ForwardingLoggerResult(buildEngineLogger));

            var p = new OptionSet
            {
                "Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) All Rights Reserved",
                "Xenko Build Tool - Version: "
                +
                String.Format(
                    "{0}.{1}.{2}",
                    typeof(Program).Assembly.GetName().Version.Major,
                    typeof(Program).Assembly.GetName().Version.Minor,
                    typeof(Program).Assembly.GetName().Version.Build) + string.Empty,
                string.Format("Usage: {0} inputPackageFile [options]* -b buildPath", exeName),
                string.Empty,
                "=== Options ===",
                string.Empty,
                { "h|help", "Show this message and exit", v => showHelp = v != null },
                { "v|verbose", "Show more verbose progress logs", v => options.Verbose = v != null },
                { "d|debug", "Show debug logs (imply verbose)", v => options.Debug = v != null },
                { "log", "Enable file logging", v => options.EnableFileLogging = v != null },
                { "disable-auto-compile", "Disable auto-compile of projects", v => options.DisableAutoCompileProjects = v != null },
                { "project-configuration=", "Project configuration", v => options.ProjectConfiguration = v },
                { "platform=", "Platform name", v => options.Platform = (PlatformType)Enum.Parse(typeof(PlatformType), v) },
                { "solution-file=", "Solution File Name", v => options.SolutionFile = v },
                { "package-id=", "Package Id from the solution file", v => options.PackageId = Guid.Parse(v) },
                { "package-file=", "Input Package File Name", v => options.PackageFile = v },
                { "o|output-path=", "Output path", v => options.OutputDirectory = v },
                { "b|build-path=", "Build path", v => options.BuildDirectory = v },
                { "log-file=", "Log build in a custom file.", v =>
                  {
                      options.EnableFileLogging = v != null;
                      options.CustomLogFileName = v;
                  } },
                { "log-pipe=", "Log pipe.", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          options.LogPipeNames.Add(v);
                      }
                  } },
                { "monitor-pipe=", "Monitor pipe.", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          options.MonitorPipeNames.Add(v);
                      }
                  } },
                { "slave=", "Slave pipe", v => options.SlavePipe = v }, // Benlitz: I don't think this should be documented
                { "server=", "This Compiler is launched as a server", v => { } },
                { "pack", "Special mode to copy assets and resources in a folder for NuGet packaging", v => packMode = true },
                { "t|threads=", "Number of threads to create. Default value is the number of hardware threads available.", v => options.ThreadCount = int.Parse(v) },
                { "test=", "Run a test session.", v => options.TestName = v },
                { "property:", "Properties. Format is name1=value1;name2=value2", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              var equalIndex = nameValue.IndexOf('=');
                              if (equalIndex == -1)
                              {
                                  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
                              }

                              options.Properties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
                          }
                      }
                  } },
                { "compile-property:", "Compile properties. Format is name1=value1;name2=value2", v =>
                  {
                      if (!string.IsNullOrEmpty(v))
                      {
                          if (options.ExtraCompileProperties == null)
                          {
                              options.ExtraCompileProperties = new Dictionary <string, string>();
                          }

                          foreach (var nameValue in v.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              var equalIndex = nameValue.IndexOf('=');
                              if (equalIndex == -1)
                              {
                                  throw new OptionException("Expect name1=value1;name2=value2 format.", "property");
                              }

                              options.ExtraCompileProperties.Add(nameValue.Substring(0, equalIndex), nameValue.Substring(equalIndex + 1));
                          }
                      }
                  } },
                {
                    "reattach-debugger=", "Reattach to a Visual Studio debugger", v =>
                    {
                        int debuggerProcessId;
                        if (!string.IsNullOrEmpty(v) && int.TryParse(v, out debuggerProcessId))
                        {
                            if (!Debugger.IsAttached)
                            {
                                using (var debugger = VisualStudioDebugger.GetByProcess(debuggerProcessId))
                                {
                                    debugger?.Attach();
                                }
                            }
                        }
                    }
                },
            };

            TextWriterLogListener fileLogListener = null;

            BuildResultCode exitCode;

            RemoteLogForwarder assetLogger = null;

            try
            {
                var unexpectedArgs = p.Parse(args);

                // Set remote logger
                assetLogger = new RemoteLogForwarder(options.Logger, options.LogPipeNames);
                GlobalLogger.GlobalMessageLogged += assetLogger;

                // Activate proper log level
                buildEngineLogger.ActivateLog(options.LoggerType);

                // Output logs to the console with colored messages
                if (options.SlavePipe == null && !options.LogPipeNames.Any())
                {
                    if (redirectLogToAppDomainAction != null)
                    {
                        globalLoggerOnGlobalMessageLogged = new LogListenerRedirectToAction(redirectLogToAppDomainAction);
                    }
                    else
                    {
                        globalLoggerOnGlobalMessageLogged = new ConsoleLogListener();
                    }
                    globalLoggerOnGlobalMessageLogged.TextFormatter = FormatLog;
                    GlobalLogger.GlobalMessageLogged += globalLoggerOnGlobalMessageLogged;
                }

                if (unexpectedArgs.Any())
                {
                    throw new OptionException("Unexpected arguments [{0}]".ToFormat(string.Join(", ", unexpectedArgs)), "args");
                }
                try
                {
                    options.ValidateOptions();
                }
                catch (ArgumentException ex)
                {
                    throw new OptionException(ex.Message, ex.ParamName);
                }

                if (showHelp)
                {
                    p.WriteOptionDescriptions(Console.Out);
                    return((int)BuildResultCode.Successful);
                }
                else if (packMode)
                {
                    PackageSessionPublicHelper.FindAndSetMSBuildVersion();

                    var csprojFile = options.PackageFile;
                    var intermediatePackagePath = options.BuildDirectory;
                    var generatedItems          = new List <(string SourcePath, string PackagePath)>();
                    var logger = new LoggerResult();
                    if (!PackAssetsHelper.Run(logger, csprojFile, intermediatePackagePath, generatedItems))
                    {
                        foreach (var message in logger.Messages)
                        {
                            Console.WriteLine(message);
                        }
                        return((int)BuildResultCode.BuildError);
                    }
                    foreach (var generatedItem in generatedItems)
                    {
                        Console.WriteLine($"{generatedItem.SourcePath}|{generatedItem.PackagePath}");
                    }
                    return((int)BuildResultCode.Successful);
                }

                // Also write logs from master process into a file
                if (options.SlavePipe == null)
                {
                    if (options.EnableFileLogging)
                    {
                        string logFileName = options.CustomLogFileName;
                        if (string.IsNullOrEmpty(logFileName))
                        {
                            string inputName = Path.GetFileNameWithoutExtension(options.PackageFile);
                            logFileName = "Logs/Build-" + inputName + "-" + DateTime.Now.ToString("yy-MM-dd-HH-mm") + ".txt";
                        }

                        string dirName = Path.GetDirectoryName(logFileName);
                        if (dirName != null)
                        {
                            Directory.CreateDirectory(dirName);
                        }

                        fileLogListener = new TextWriterLogListener(new FileStream(logFileName, FileMode.Create))
                        {
                            TextFormatter = FormatLog
                        };
                        GlobalLogger.GlobalMessageLogged += fileLogListener;
                    }

                    options.Logger.Info("BuildEngine arguments: " + string.Join(" ", args));
                    options.Logger.Info("Starting builder.");

                    try
                    {
                        var      baseDirectory = Path.Combine(options.BuildDirectory, @"../../../../../");
                        var      changeFile = baseDirectory + "/files_changed";
                        var      buildFile = baseDirectory + "/files_built";
                        var      skipFile = baseDirectory + "/always_build";
                        long     files_changed_ticks = 0, files_built_ticks = 0;
                        string[] buildlines = null;
                        string   platform   = options.Platform.ToString() + "-" + options.ProjectConfiguration;

                        if (File.Exists(changeFile))
                        {
                            long.TryParse(File.ReadAllText(changeFile), out files_changed_ticks);
                        }

                        if (File.Exists(buildFile))
                        {
                            buildlines = File.ReadAllLines(buildFile);
                            for (int i = 0; i < buildlines.Length; i += 2)
                            {
                                if (buildlines[i] == platform)
                                {
                                    long.TryParse(buildlines[i + 1], out files_built_ticks);
                                    // also update with now time
                                    buildlines[i + 1] = System.DateTime.Now.Ticks.ToString();
                                }
                            }
                        }

                        if (File.Exists(skipFile))
                        {
                            options.Logger.Info("Found always_build, so always building assets.");
                        }
                        else if (Process.GetProcessesByName("Focus.GameStudio").Length == 0)
                        {
                            options.Logger.Warning("Focus.GameStudio does not appear to be running, so the AssetCompiler will always rebuild assets.");
                        }
                        else if (files_changed_ticks > 0 && files_built_ticks > 0 && files_built_ticks > files_changed_ticks)
                        {
                            options.Logger.Info("All Assets/ and Resources/ appear up date for " + platform + ", so skipping recompilation. If this is a mistake, delete files_changed and files_built in the root project directory. If you want to always build assets, make a file called always_build in the root project directory.");
                            return(0);
                        }

                        // if there was no changefile, do it now
                        if (File.Exists(changeFile) == false)
                        {
                            File.WriteAllText(changeFile, System.DateTime.Now.Ticks.ToString());
                        }

                        // update file with changes
                        if (File.Exists(buildFile) == false)
                        {
                            File.WriteAllText(buildFile, platform + "\n" + System.DateTime.Now.Ticks.ToString());
                        }
                        else
                        {
                            File.WriteAllLines(buildFile, buildlines);
                            if (files_built_ticks <= 0)
                            {
                                File.AppendAllText(buildFile, platform + "\n" + System.DateTime.Now.Ticks.ToString());
                            }
                        }
                    }
                    catch (Exception)
                    {
                        options.Logger.Warning("Error reading/writing files_changed and/or files_built to see if we can skip asset compilation. Reverting to building them.");
                    }
                }
                else
                {
                    IsSlave = true;
                }

                if (!string.IsNullOrEmpty(options.TestName))
                {
                    var test = new TestSession();
                    test.RunTest(options.TestName, options.Logger);
                    exitCode = BuildResultCode.Successful;
                }
                else
                {
                    builder = new PackageBuilder(options);
                    if (!IsSlave && redirectLogToAppDomainAction == null)
                    {
                        Console.CancelKeyPress += OnConsoleOnCancelKeyPress;
                    }
                    exitCode = builder.Build();
                }
            }
            catch (OptionException e)
            {
                options.Logger.Error($"Command option '{e.OptionName}': {e.Message}");
                exitCode = BuildResultCode.CommandLineError;
            }
            catch (Exception e)
            {
                options.Logger.Error($"Unhandled exception", e);
                exitCode = BuildResultCode.BuildError;
            }
            finally
            {
                // Flush and close remote logger
                if (assetLogger != null)
                {
                    GlobalLogger.GlobalMessageLogged -= assetLogger;
                    assetLogger.Dispose();
                }

                if (fileLogListener != null)
                {
                    GlobalLogger.GlobalMessageLogged -= fileLogListener;
                    fileLogListener.LogWriter.Close();
                }

                // Output logs to the console with colored messages
                if (globalLoggerOnGlobalMessageLogged != null)
                {
                    GlobalLogger.GlobalMessageLogged -= globalLoggerOnGlobalMessageLogged;
                }
                if (builder != null && !IsSlave && redirectLogToAppDomainAction == null)
                {
                    Console.CancelKeyPress -= OnConsoleOnCancelKeyPress;
                }

                // Reset cache hold by YamlSerializer
                YamlSerializer.Default.ResetCache();
            }
            return((int)exitCode);
        }
Exemple #5
0
        private Assembly LoadAssemblyFromPathInternal(string assemblyFullPath)
        {
            if (assemblyFullPath == null)
            {
                throw new ArgumentNullException("assemblyFullPath");
            }

            string safeShadowPath = null;

            try
            {
                assemblyFullPath = Path.GetFullPath(assemblyFullPath);

                lock (loadedAssemblies)
                {
                    Assembly assembly;
                    if (loadedAssemblies.TryGetValue(assemblyFullPath, out assembly))
                    {
                        return(assembly);
                    }

                    if (!File.Exists(assemblyFullPath))
                    {
                        return(null);
                    }

                    // Create a shadow copy of the assembly to load
                    safeShadowPath = CopySafeShadow(assemblyFullPath);
                    if (safeShadowPath == null)
                    {
                        log.Error("Cannot create a shadow copy for assembly [{0}]", assemblyFullPath);
                        return(null);
                    }

                    // Load the assembly into the current AppDomain
                    // TODO: Is using AppDomain would provide more opportunities for unloading?
                    assembly = Assembly.LoadFile(safeShadowPath);
                    loadedAssemblies.Add(assemblyFullPath, assembly);

                    // Force assembly resolve with proper name
                    // (doing it here, because if done later, loadingInstance will be set to null and it won't work)
                    Assembly.Load(assembly.FullName);

                    // Make sure that all referenced assemblies are loaded here
                    foreach (var assemblyRef in assembly.GetReferencedAssemblies())
                    {
                        Assembly.Load(assemblyRef);
                    }

                    // Make sure that Module initializer are called
                    if (assembly.GetTypes().Length > 0)
                    {
                        foreach (var module in assembly.Modules)
                        {
                            RuntimeHelpers.RunModuleConstructor(module.ModuleHandle);
                        }
                    }
                    return(assembly);
                }
            }
            catch (Exception exception)
            {
                log.Error("Error while loading assembly reference [{0}]", exception, safeShadowPath ?? assemblyFullPath);
                var loaderException = exception as ReflectionTypeLoadException;
                if (loaderException != null)
                {
                    foreach (var exceptionForType in loaderException.LoaderExceptions)
                    {
                        log.Error("Unable to load type. See exception.", exceptionForType);
                    }
                }
            }
            return(null);
        }
        private Assembly LoadAssemblyFromPathInternal([NotNull] string assemblyFullPath)
        {
            if (assemblyFullPath is null)
            {
                throw new ArgumentNullException(nameof(assemblyFullPath));
            }

            assemblyFullPath = Path.GetFullPath(assemblyFullPath);

            try
            {
                lock (loadedAssemblies)
                {
                    if (loadedAssembliesByName.TryGetValue(assemblyFullPath, out LoadedAssembly loadedAssembly))
                    {
                        return(loadedAssembly.Assembly);
                    }

                    if (!File.Exists(assemblyFullPath))
                    {
                        return(null);
                    }

                    // Find pdb (if it exists)
                    var pdbFullPath = Path.ChangeExtension(assemblyFullPath, ".pdb");
                    if (!File.Exists(pdbFullPath))
                    {
                        pdbFullPath = null;
                    }

                    // PreLoad the assembly into memory without locking it
                    var assemblyBytes = File.ReadAllBytes(assemblyFullPath);
                    var pdbBytes      = pdbFullPath != null?File.ReadAllBytes(pdbFullPath) : null;

                    // Load the assembly into the current AppDomain
                    Assembly assembly;
                    if (new UDirectory(AppDomain.CurrentDomain.BaseDirectory) == new UFile(assemblyFullPath).GetFullDirectory())
                    {
                        // If loading from base directory, don't even try to load through byte array, as Assembly.Load will notice there is a "safer" version to load
                        // This happens usually when opening Stride assemblies themselves
                        assembly = Assembly.LoadFrom(assemblyFullPath);
                    }
                    else
                    {
                        // Load .deps.json file (if any)
                        var depsFile = Path.ChangeExtension(assemblyFullPath, ".deps.json");
                        Dictionary <string, string> dependenciesMapping = null;
                        if (File.Exists(depsFile))
                        {
                            // Read file
                            var dependenciesReader         = new DependencyContextJsonReader();
                            DependencyContext dependencies = null;
                            using (var dependenciesStream = File.OpenRead(depsFile))
                            {
                                dependencies = dependenciesReader.Read(dependenciesStream);
                            }

                            // Locate NuGet package folder
                            var settings             = NuGet.Configuration.Settings.LoadDefaultSettings(Path.GetDirectoryName(assemblyFullPath));
                            var globalPackagesFolder = NuGet.Configuration.SettingsUtility.GetGlobalPackagesFolder(settings);

                            // Build list of assemblies listed in .deps.json file
                            dependenciesMapping = new Dictionary <string, string>();
                            foreach (var library in dependencies.RuntimeLibraries)
                            {
                                if (library.Path is null)
                                {
                                    continue;
                                }

                                foreach (var runtimeAssemblyGroup in library.RuntimeAssemblyGroups)
                                {
                                    foreach (var runtimeFile in runtimeAssemblyGroup.RuntimeFiles)
                                    {
                                        var fullPath = Path.Combine(globalPackagesFolder, library.Path, runtimeFile.Path);
                                        if (File.Exists(fullPath))
                                        {
                                            var assemblyName = Path.GetFileNameWithoutExtension(runtimeFile.Path);

                                            // TODO: Properly deal with file duplicates (same file in multiple package, or RID conflicts)
                                            if (!dependenciesMapping.ContainsKey(assemblyName))
                                            {
                                                dependenciesMapping.Add(assemblyName, fullPath);
                                            }
                                        }
                                    }
                                }

                                // It seems .deps.json files don't contain library info if referencer is non-RID specific and dependency is RID specific
                                // (i.e. compiling Game project without runtime identifier and a dependency needs runtime identifier)
                                // TODO: Look for a proper way to query that properly, maybe using NuGet API? however some constraints are:
                                // - limited info (only .deps.json available from path, no project info; we might need to reconstruct a proper NuGet restore request from .deps.json)
                                // - need to be fast (make sure to use NuGet caching mechanism)
                                if (library.RuntimeAssemblyGroups.Count == 0)
                                {
                                    var runtimeFolder = new[] { "win", "any" }
                                    .Select(runtime => Path.Combine(globalPackagesFolder, library.Path, "runtimes", runtime))
                                    .Where(Directory.Exists)
                                    .SelectMany(folder => Directory.EnumerateDirectories(Path.Combine(folder, "lib")))
                                    .FirstOrDefault(file => Path.GetFileName(file).StartsWith("net"));     // Only consider framework netXX and netstandardX.X
                                    if (runtimeFolder != null)
                                    {
                                        foreach (var runtimeFile in Directory.EnumerateFiles(runtimeFolder, "*.dll"))
                                        {
                                            var assemblyName = Path.GetFileNameWithoutExtension(runtimeFile);

                                            // TODO: Properly deal with file duplicates (same file in multiple package, or RID conflicts)
                                            if (!dependenciesMapping.ContainsKey(assemblyName))
                                            {
                                                dependenciesMapping.Add(assemblyName, runtimeFile);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        // TODO: Is using AppDomain would provide more opportunities for unloading?
                        assembly = pdbBytes != null?Assembly.Load(assemblyBytes, pdbBytes) : Assembly.Load(assemblyBytes);

                        loadedAssembly = new LoadedAssembly(this, assemblyFullPath, assembly, dependenciesMapping);
                        loadedAssemblies.Add(loadedAssembly);
                        loadedAssembliesByName.Add(assemblyFullPath, loadedAssembly);

                        // Force assembly resolve with proper name (with proper context)
                        var previousSearchDirectory = currentSearchDirectory;
                        var previousContainer       = currentContainer;
                        try
                        {
                            currentContainer       = this;
                            currentSearchDirectory = Path.GetDirectoryName(assemblyFullPath);

                            Assembly.Load(assembly.FullName);
                        }
                        finally
                        {
                            currentContainer       = previousContainer;
                            currentSearchDirectory = previousSearchDirectory;
                        }
                    }

                    // Make sure there is no duplicate
                    Debug.Assert(!assemblyToContainers.TryGetValue(assembly, out var _));
                    // Add to mapping
                    assemblyToContainers.GetValue(assembly, _ => loadedAssembly);

                    // Make sure that Module initializer are called
                    foreach (var module in assembly.Modules)
                    {
                        RuntimeHelpers.RunModuleConstructor(module.ModuleHandle);
                    }
                    return(assembly);
                }
            }
            catch (Exception exception)
            {
                log.Error($"Error while loading assembly reference [{assemblyFullPath}]", exception);
                var loaderException = exception as ReflectionTypeLoadException;
                if (loaderException != null)
                {
                    foreach (var exceptionForType in loaderException.LoaderExceptions)
                    {
                        log.Error("Unable to load type. See exception.", exceptionForType);
                    }
                }
            }
            return(null);
        }
 public static void LoadXenkoAssemblies()
 {
     RuntimeHelpers.RunModuleConstructor(typeof(Asset).Module.ModuleHandle);
 }
Exemple #8
0
        private Assembly LoadAssemblyFromPathInternal(string assemblyFullPath)
        {
            if (assemblyFullPath == null)
            {
                throw new ArgumentNullException("assemblyFullPath");
            }

            assemblyFullPath = Path.GetFullPath(assemblyFullPath);

            try
            {
                lock (loadedAssemblies)
                {
                    LoadedAssembly loadedAssembly;
                    if (loadedAssembliesByName.TryGetValue(assemblyFullPath, out loadedAssembly))
                    {
                        return(loadedAssembly.Assembly);
                    }

                    if (!File.Exists(assemblyFullPath))
                    {
                        return(null);
                    }

                    // Find pdb (if it exists)
                    var pdbFullPath = Path.ChangeExtension(assemblyFullPath, ".pdb");
                    if (!File.Exists(pdbFullPath))
                    {
                        pdbFullPath = null;
                    }

                    // PreLoad the assembly into memory without locking it
                    var assemblyBytes = File.ReadAllBytes(assemblyFullPath);
                    var pdbBytes      = pdbFullPath != null?File.ReadAllBytes(pdbFullPath) : null;

                    // Load the assembly into the current AppDomain
                    Assembly assembly;
                    if (new UDirectory(AppDomain.CurrentDomain.BaseDirectory) == new UFile(assemblyFullPath).GetFullDirectory())
                    {
                        // If loading from base directory, don't even try to load through byte array, as Assembly.Load will notice there is a "safer" version to load
                        // This happens usually when opening Xenko assemblies themselves
                        assembly = Assembly.LoadFrom(assemblyFullPath);
                    }
                    else
                    {
                        // TODO: Is using AppDomain would provide more opportunities for unloading?
                        assembly = pdbBytes != null?Assembly.Load(assemblyBytes, pdbBytes) : Assembly.Load(assemblyBytes);

                        loadedAssembly = new LoadedAssembly(assemblyFullPath, assembly);
                        loadedAssemblies.Add(loadedAssembly);
                        loadedAssembliesByName.Add(assemblyFullPath, loadedAssembly);

                        // Force assembly resolve with proper name
                        // (doing it here, because if done later, loadingInstance will be set to null and it won't work)
                        Assembly.Load(assembly.FullName);
                    }

                    // Make sure that all referenced assemblies are loaded here
                    foreach (var assemblyRef in assembly.GetReferencedAssemblies())
                    {
                        Assembly.Load(assemblyRef);
                    }

                    // Make sure that Module initializer are called
                    if (assembly.GetTypes().Length > 0)
                    {
                        foreach (var module in assembly.Modules)
                        {
                            RuntimeHelpers.RunModuleConstructor(module.ModuleHandle);
                        }
                    }
                    return(assembly);
                }
            }
            catch (Exception exception)
            {
                log.Error($"Error while loading assembly reference [{assemblyFullPath}]", exception);
                var loaderException = exception as ReflectionTypeLoadException;
                if (loaderException != null)
                {
                    foreach (var exceptionForType in loaderException.LoaderExceptions)
                    {
                        log.Error("Unable to load type. See exception.", exceptionForType);
                    }
                }
            }
            return(null);
        }