Beispiel #1
0
 public BuildMachine(BuildMachineSettings settings)
 {
     Settings       = settings;
     State          = BuildMachineState.Idle;
     CurrentTimeout = 0;
     NeedClean      = false;
 }
Beispiel #2
0
 /// <summary>
 /// Returns the build template for the given configuration.
 /// </summary>
 /// <param name="sConfiguration">Configuration as returned by CMake.</param>
 /// <returns></returns>
 public static ezBuildTemplate Create(BuildMachineSettings settings, string sBuildType)
 {
     if (sBuildType == "C++")
     {
         if (settings.Configuration.StartsWith("Win"))
         {
             bool bIs64Bit = settings.Configuration.Contains("64");
             if (settings.Configuration.Contains("2012"))
             {
                 return(new ezBuildWinVS(settings, VSVersion.VS2012, bIs64Bit));
             }
             else if (settings.Configuration.Contains("2013"))
             {
                 return(new ezBuildWinVS(settings, VSVersion.VS2013, bIs64Bit));
             }
             else if (settings.Configuration.Contains("2015"))
             {
                 return(new ezBuildWinVS(settings, VSVersion.VS2015, bIs64Bit));
             }
         }
         else if (settings.Configuration.StartsWith("Osx"))
         {
             if (settings.Configuration.Contains("MakeClang"))
             {
                 return(new BuildMake(settings));
             }
             else if (settings.Configuration.Contains("XcodeClang"))
             {
                 return(new BuildOsxXcode(settings));
             }
         }
         else if (settings.Configuration.StartsWith("Linux"))
         {
             if (settings.Configuration.Contains("MakeGcc"))
             {
                 return(new BuildMake(settings));
             }
         }
     }
     else if (sBuildType == "D")
     {
         if (settings.Configuration.StartsWith("WinVs"))
         {
             bool bIs64Bit = settings.Configuration.Contains("64");
             if (settings.Configuration.Contains("2012"))
             {
                 return(new ezBuildWinD(settings, VSVersion.VS2012, bIs64Bit));
             }
             else if (settings.Configuration.Contains("2013"))
             {
                 return(new ezBuildWinD(settings, VSVersion.VS2013, bIs64Bit));
             }
             else if (settings.Configuration.Contains("2015"))
             {
                 return(new ezBuildWinD(settings, VSVersion.VS2015, bIs64Bit));
             }
         }
     }
     return(null);
 }
Beispiel #3
0
        public bool Init(BuildMachineSettings settings)
        {
            _Settings = settings;

            try
            {
                // Make sure the given parameter is valid.
                if (!System.IO.Path.IsPathRooted(_Settings.AbsCodePath))
                {
                    Console.WriteLine("SVN Init failed: The path '{0}' is not absolute!", _Settings.AbsCodePath);
                    return(false);
                }

                if (!System.IO.Directory.Exists(_Settings.AbsCodePath))
                {
                    Console.WriteLine("SVN Init failed: The path '{0}' does not exist!", _Settings.AbsCodePath);
                    return(false);
                }

                Console.WriteLine("SVN Init: Code path: '{0}'.", _Settings.AbsCodePath);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return(false);
            }
            return(true);
        }
Beispiel #4
0
        public bool Init(BuildMachineSettings settings)
        {
            _Result.Clean();
            _Settings = settings;

            try
            {
                // Make sure the given parameter is valid.
                if (!System.IO.Path.IsPathRooted(_Settings.AbsCMakeWorkspace))
                {
                    Console.WriteLine("CMake Init failed: The path '{0}' is not absolute!", _Settings.AbsCMakeWorkspace);
                    return(false);
                }

                if (!System.IO.Directory.Exists(_Settings.AbsCMakeWorkspace))
                {
                    Console.WriteLine("CMake Init failed: The path '{0}' does not exist!", _Settings.AbsCMakeWorkspace);
                    return(false);
                }

                Console.WriteLine("CMake Init: Workspace: '{0}'.", _Settings.AbsCMakeWorkspace);

                // Run process to get configuration and code dir.
                ezProcessHelper.ProcessResult res = ezProcessHelper.RunExternalExe("cmake", ".", _Settings.AbsCMakeWorkspace, _Result);

                // Determine the configuration this server is taking care of if non is set.
                if (String.IsNullOrEmpty(_Settings.Configuration) && !DetermineConfiguration())
                {
                    return(false);
                }

                Console.WriteLine("CMake Init: Configuration: '{0}'.", _Settings.Configuration);

                // Determine the code directory this CMake workspace belongs to.
                if (!DetermineCodeDirectory())
                {
                    return(false);
                }

                // Determine the bin directory where executables are build to.
                if (!DetermineBinDirectory())
                {
                    return(false);
                }

                Console.WriteLine("CMake Init: Code Path: '{0}'.", _Settings.AbsCodePath);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return(false);
            }

            return(true);
        }
Beispiel #5
0
 /// <summary>
 /// Returns the test template for the given configuration.
 /// </summary>
 /// <param name="sConfiguration">Configuration as returned by CMake.</param>
 /// <returns></returns>
 public static ezTestTemplate Create(BuildMachineSettings settings)
 {
     if (settings.Configuration.StartsWith("WinUWP"))
     {
         return(new ezTestUWP());
     }
     else
     {
         return(new ezTestDefault());
     }
 }
Beispiel #6
0
 private string HandlePOSTConfiguration(BuildMachineSettings settings)
 {
     lock (_Lock)
     {
         // We got a new build machine! We use it's configurationName as it's ID as it should be chosen unique by the admin.
         _Machines[settings.ConfigurationName] = new BuildMachine(settings);
         DetermineCurrentRevisionOfBuildMachine(_Machines[settings.ConfigurationName]);
         Console.WriteLine("HandlePOSTConfiguration: New machine '{0}' connected!", settings.ConfigurationName);
         return(settings.ConfigurationName);
     }
 }
Beispiel #7
0
        bool LoadSettings()
        {
            try
            {
                string sResultPath = System.IO.Path.Combine(_Result.Settings.AbsCMakeWorkspace, "settings.json");
                if (!System.IO.File.Exists(sResultPath))
                {
                    Console.WriteLine("The build machine settings are not set yet.\n" +
                                      "Open '{0}', change the settings and restart this application.", sResultPath);
                    SaveSettings();
                    return(false);
                }
                string sSerializedResult      = System.IO.File.ReadAllText(sResultPath, Encoding.UTF8);
                BuildMachineSettings settings = JsonConvert.DeserializeObject <BuildMachineSettings>(sSerializedResult);

                // We take the whole settings except for the 'AbsCMakeWorkspace' which is the only parameter that is given to as as
                // a command line parameter and could differ if someone copied the settings from another build machine.
                settings.AbsCMakeWorkspace = _Result.Settings.AbsCMakeWorkspace;
                if (String.IsNullOrEmpty(settings.BuildType))
                {
                    settings.BuildType = "RelWithDebInfo";
                }
                _Result.Settings = settings;

                if (!CheckSettings())
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Writing json file failed: {0}", ex.Message);
                return(false);
            }
            return(true);
        }
Beispiel #8
0
 public BuildOsxXcode(BuildMachineSettings settings)
 {
     _settings = settings;
 }
Beispiel #9
0
 public ezBuildWinD(BuildMachineSettings settings, VSVersion version, bool bIs64Bit)
 {
     _settings = settings;
     _Version  = version;
     _bIs64Bit = bIs64Bit;
 }
Beispiel #10
0
        private BuildStepResults DeployAppX(ezCMake.TestTarget target, BuildMachineSettings settings, out string fullPackageName)
        {
            Console.WriteLine("Deploying AppX ...");

            BuildStepResults result = new BuildStepResults();

            fullPackageName = "";

            string absSlnPath = Path.Combine(settings.AbsCMakeWorkspace, "ezEngine.sln");

            if (!File.Exists(absSlnPath))
            {
                result.Error("Visual Studio solution '{0}' does not exist.", absSlnPath);
                return(result);
            }


            // VSLauncher vs using devenv.exe directly.
            //
            // Pro VSLauncher:
            // - It picks always the appropriate VS version
            // - We know more certainly where it is
            //
            // Con VSLauncher:
            // - Spawns devenv.exe and closes again (we don't know when devenv.exe finishes or if it came up in the first place)
            // - No console output

            //string VSLauncherAbsPath = Environment.ExpandEnvironmentVariables(VSLauncherLocation);
            //if (!File.Exists(VSLauncherAbsPath))
            //{
            //  result.Error("Did not find Visual Studio launcher at '{0}'.", VSLauncherAbsPath);
            //  return result;
            //}

            // Using this registry key we should always get the newest devenv version.
            // Since newer versions can use old compilers & SDKs this should be perfectly fine.
            // https://social.msdn.microsoft.com/Forums/vstudio/en-US/568e32af-d724-4ac6-8e8f-72181c4320b3/set-default-version-of-visual-studio?forum=vssetup
            string devEnvPath;

            try
            {
                using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\devenv.exe"))
                {
                    if (key != null)
                    {
                        devEnvPath = key.GetValue("") as string;
                        if (devEnvPath == null)
                        {
                            result.Error("Failed to read Visual Studio location from registry key: No string value in key found.");
                            return(result);
                        }
                    }
                    else
                    {
                        result.Error("Failed to read Visual Studio location from registry key: Registry key not found.");
                        return(result);
                    }
                }
            }
            catch (Exception e)
            {
                result.Error("Failed to read Visual Studio location from registry key: {0}", e);
                return(result);
            }

            // Use ".com" version which writes into stdout
            devEnvPath = devEnvPath.Replace("devenv.exe", "devenv.com");

            if (!File.Exists(devEnvPath))
            {
                result.Error("Did not find Visual Studio installation at '{0}'.", devEnvPath);
                return(result);
            }

            // "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.com" "F:\Development\current_development\ezEngine\build_uwp64\ezEngine.sln" /Deploy "RelWithDebInfo|x64" /project CoreTest

            string platform             = settings.Configuration.EndsWith("64") ? "x64" : "Win32"; // No ARM support yet.
            var    deployProcessResults = ezProcessHelper.RunExternalExe(devEnvPath,
                                                                         string.Format("\"{0}\" /Deploy \"{1}|{2}\" /project {3}", absSlnPath, settings.BuildType, platform, target.Name), null, result);

            result.Duration = deployProcessResults.Duration;
            if (deployProcessResults.ExitCode != 0)
            {
                result.Error("Deployment failed:\n{0}", deployProcessResults.StdOut);
                result.Success = false;
            }
            else
            {
                // Get full package name from deploy output.
                // From the build configuration we only know the package name, not the full identifier. This little parse saves us from searching the package registry.
                string fullPackageNameStartString = "Full package name: \"";
                int    begin = deployProcessResults.StdOut.LastIndexOf(fullPackageNameStartString) + fullPackageNameStartString.Length;
                int    end   = deployProcessResults.StdOut.IndexOf("\"", begin);
                if (begin < 0 || end < 0)
                {
                    result.Error("Failed to parse full package name from Visual Studio output. Output was:\n'{0}'.", deployProcessResults.StdOut);
                    return(result);
                }
                fullPackageName = deployProcessResults.StdOut.Substring(begin, end - begin);

                result.Success = true;
            }

            return(result);
        }
Beispiel #11
0
 static private string GetFileserverPath(BuildMachineSettings settings)
 {
     return(Path.Combine(settings.AbsCodePath, relativeFileservePath));
 }
Beispiel #12
0
        public override ezTest.TestTargetResult BuildTarget(ezCMake.TestTarget target, BuildMachineSettings settings)
        {
            ezTest.TestTargetResult res = new ezTest.TestTargetResult();
            res.Name = target.Name;
            res.NeedsHardwareAccess = target.NeedsHardwareAccess;
            res.Experimental        = target.Experimental;


            // Prepare output path (may fail, and we don't want to go through the rest if it does)
            string outputFilename = GetOutputFileName(target, settings);
            string absOutputPath  = System.IO.Path.Combine(settings.AbsOutputFolder, outputFilename);

            if (!DeleteOutputFile(absOutputPath, ref res))
            {
                return(res);
            }

            // Deploy app.
            string fullPackageName;
            var    deployResult = DeployAppX(target, settings, out fullPackageName);

            res.MergeIn(deployResult);
            if (!deployResult.Success)
            {
                return(res);
            }

            // Start AppX
            uint appXPid;
            var  startResult = StartAppX(fullPackageName, GetDefaultTestArgs(outputFilename, settings), out appXPid);

            res.MergeIn(startResult);
            if (!startResult.Success)
            {
                return(res);
            }
            Process appXProcess;

            try
            {
                appXProcess = Process.GetProcessById((int)appXPid);
            }
            catch (Exception e)
            {
                res.Error("Failed to get process handle to test app: {0}", e);
                return(res);
            }

            // Start fileserver.
            string absFilerserveFilename = GetFileserverPath(settings);

            if (!File.Exists(absFilerserveFilename))
            {
                res.Error("No fileserver found. File '{0}' does not exist.", absFilerserveFilename);
            }
            else
            {
                string absBinDir       = Path.Combine(settings.AbsBinPath, settings.Configuration);
                string absTestDataPath = Path.Combine(settings.AbsCodePath, relativeTestDataPath);
                // 20s timeout for connect, 2s timeout for closing after connection loss.
                string args = string.Format("-specialdirs project \"{0}\" eztest \"{1}\" -fs_start -fs_wait_timeout 20 -fs_close_timeout 2", absTestDataPath, settings.AbsOutputFolder);
                res.ProcessRes = ezProcessHelper.RunExternalExe(absFilerserveFilename, args, absBinDir, res);
                res.Duration  += res.ProcessRes.Duration;
                res.Success    = (res.ProcessRes.ExitCode == 0);
            }

            // Top watch.

            // Check whether the AppX is dead by now.
            if (!appXProcess.HasExited)
            {
                res.Error("Fileserve is no longer running but the AppX is.");
                res.Success = false;
                appXProcess.Kill();
            }
            // Can't read exit code: "Process was not started by this object, so requested information cannot be determined"

            /*else
             * {
             * if (appXProcess.ExitCode != 0)
             * {
             *  res.Error("Test AppX exited with {0}", appXProcess.ExitCode);
             *  res.Success = false;
             * }
             * }*/
            appXProcess.Dispose();
            appXProcess = null;

            // Read test output.
            if (File.Exists(absOutputPath))
            {
                res.TestResultJSON = File.ReadAllText(absOutputPath, Encoding.UTF8);
                //TODO: use test json output as stdout substitute until pipes are implemented.
                res.ProcessRes.StdOut = res.TestResultJSON;
                try
                {
                    // Parse test output to figure out what the result is as we can't use the exit code.
                    var values = Newtonsoft.Json.JsonConvert.DeserializeObject <System.Collections.Generic.Dictionary <string, dynamic> >(res.TestResultJSON);
                    var errors = values["errors"] as Newtonsoft.Json.Linq.JArray;
                    res.Success = errors.Count == 0;
                }
                catch (Exception e)
                {
                    res.Success = false;
                    res.Error("Failed to parse test output: '{0}'", e.ToString());
                }
            }
            else
            {
                res.Error("No output file present!");
                res.Success = false;
            }

            if (!res.Success && !res.Experimental)
            {
                res.Error("Testing '{0}' failed!", res.Name);
            }
            return(res);
        }
Beispiel #13
0
 static protected string GetDefaultTestArgs(string outputFilename, BuildMachineSettings settings)
 {
     return(string.Format("-json \"{0}\" -rev {1} -nogui -all", outputFilename, settings.Revision));
 }
Beispiel #14
0
        private void HandleRequest(object state)
        {
            HttpListenerContext context = (HttpListenerContext)state;

            try
            {
                HttpListenerRequest request = context.Request;
                // Get message text
                string sMessageText;
                using (var reader = new StreamReader(request.InputStream, UTF8Encoding.UTF8))
                {
                    sMessageText = reader.ReadToEnd();
                }

                string sResponseMessage = null;
                // If no query was given, show help page
                if (request.QueryString.AllKeys.Count() == 0)
                {
                    sResponseMessage = ShowHelpPage();
                }
                else
                {
                    // Retrieve type of message.
                    ezBuildRequestMessageType eType = ezBuildRequestMessageType.INVALID_REQUEST;
                    try
                    {
                        if (request.QueryString.AllKeys.Contains("type"))
                        {
                            eType = (ezBuildRequestMessageType)Convert.ToInt32(request.QueryString["type"]);
                        }
                    }
                    catch (FormatException)
                    {
                        eType = ezBuildRequestMessageType.INVALID_REQUEST;
                        Console.WriteLine("'type' of request invalid or not present!");
                        context.Response.StatusCode = 400; // Bad Request
                        context.Response.OutputStream.Close();
                        return;
                    }

                    // Handle message
                    switch (eType)
                    {
                    case ezBuildRequestMessageType.POSTConfiguration:
                    {
                        BuildMachineSettings settings = Newtonsoft.Json.JsonConvert.DeserializeObject <BuildMachineSettings>(sMessageText);
                        sResponseMessage = HandlePOSTConfiguration(settings);
                    }
                    break;

                    case ezBuildRequestMessageType.GETPing:
                    {
                        string sID = request.QueryString["ID"];
                        sResponseMessage = HandleGETPing(sID);
                    }
                    break;

                    case ezBuildRequestMessageType.GETWork:
                    {
                        string sID = request.QueryString["ID"];
                        sResponseMessage = HandleGETWork(sID);
                    }
                    break;

                    case ezBuildRequestMessageType.POSTBuildResult:
                    {
                        string sID       = request.QueryString["ID"];
                        string sFilename = request.QueryString["File"];
                        sResponseMessage = POSTBuildResult(sID, sFilename, sMessageText);
                    }
                    break;

                    case ezBuildRequestMessageType.GETStatus:
                    {
                        sResponseMessage = HandleGetStatus();
                    }
                    break;

                    case ezBuildRequestMessageType.GETCheckHEADRevision:
                    {
                        _iLastSVNCheckTimestamp = 0;
                        sResponseMessage        = "Checking SVN Request received.";
                    }
                    break;

                    case ezBuildRequestMessageType.GETPostToAddress:
                    {
                        string sAddress       = request.QueryString["TO"];
                        int    iStartRevision = 0;
                        if (request.QueryString.AllKeys.Contains("StartRevision"))
                        {
                            iStartRevision = Convert.ToInt32(request.QueryString["StartRevision"]);
                        }
                        sResponseMessage = HandleGetPostToAddress(sAddress, iStartRevision);
                    }
                    break;

                    case ezBuildRequestMessageType.GETPause:
                    {
                        sResponseMessage = HandleGetPause(true);
                    }
                    break;

                    case ezBuildRequestMessageType.GETResume:
                    {
                        sResponseMessage = HandleGetPause(false);
                    }
                    break;

                    case ezBuildRequestMessageType.GETEnableHibernateOnIdle:
                    {
                        sResponseMessage = HandleGetHibernate(true);
                    }
                    break;

                    case ezBuildRequestMessageType.GETDisableHibernateOnIdle:
                    {
                        sResponseMessage = HandleGetHibernate(false);
                    }
                    break;

                    case ezBuildRequestMessageType.GETCleanBuild:
                    {
                        string sID = request.QueryString["ID"];
                        sResponseMessage = HandleGetCleanBuild(sID);
                    }
                    break;

                    default:
                        Console.WriteLine("HandleRequest: invalid message type: '{0}'!", eType);
                        break;
                    }
                }

                // Send response
                if (sResponseMessage == null)
                {
                    context.Response.StatusCode = 400; // Bad Request
                    context.Response.OutputStream.Close();
                }
                else
                {
                    context.Response.StatusCode  = 200; // OK
                    context.Response.SendChunked = true;
                    var bytes = Encoding.UTF8.GetBytes(sResponseMessage);
                    context.Response.OutputStream.Write(bytes, 0, bytes.Length);
                    context.Response.OutputStream.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("HandleRequest Failed: {0}", ex.Message);
                context.Response.StatusCode = 400; // Bad Request
                context.Response.OutputStream.Close();
            }
        }
Beispiel #15
0
 public bool Init(BuildMachineSettings settings)
 {
     _Settings = settings;
     return(true);
 }
Beispiel #16
0
 public abstract ezTest.TestTargetResult BuildTarget(ezCMake.TestTarget target, BuildMachineSettings settings);
Beispiel #17
0
 public BuildProcessResult()
 {
     Settings = new BuildMachineSettings();
 }
Beispiel #18
0
 public BuildMake(BuildMachineSettings settings)
 {
     _settings = settings;
 }
Beispiel #19
0
 protected string GetOutputFileName(ezCMake.TestTarget target, BuildMachineSettings settings)
 {
     return(string.Format("{0}_{1}_{2}.json", settings.Configuration, settings.Revision, target.Name));
 }