/// <summary>
 /// Static constructor for the <see cref="CudafyModes"/> class.
 /// Sets CodeGen to CudaC, Compiler to CudaNvcc, Target to Cuda and Mode to Cuda.
 /// </summary>
 static CudafyModes()
 {
     //CodeGen = eGPUCodeGenerator.CudaC;
     Compiler = eGPUCompiler.CudaNvcc;
     Target = eGPUType.Cuda;
     Mode = eCudafyQuickMode.Cuda;
     DeviceId = 0;
 }
        /// <summary>
        /// Compiles the module based on current Cuda source code and options.
        /// </summary>
        /// <param name="mode">The mode.</param>
        /// <param name="deleteGeneratedCode">if set to <c>true</c> delete generated code on success.</param>
        /// <param name="binary">Compile to binary if true.</param>
        /// <returns>The compile arguments.</returns>
        /// <exception cref="CudafyCompileException">No source code or compilation error.</exception>
        public string Compile(eGPUCompiler mode, bool deleteGeneratedCode = false, eCudafyCompileMode compileMode = eCudafyCompileMode.Default)
        {
            string ts = string.Empty;
            if ((mode & eGPUCompiler.CudaNvcc) == eGPUCompiler.CudaNvcc)
            {
                CompilerOutput = string.Empty;
                _PTXModules.Clear();
                _BinaryModules.Clear();
                if (!HasSourceCode)
                    throw new CudafyCompileException(CudafyCompileException.csNO_X_SOURCE_CODE_PRESENT_IN_CUDAFY_MODULE, "CUDA");

                if (CompilerOptionsList.Count == 0)
                {
                    var opt = IntPtr.Size == 4 ? NvccCompilerOptions.Createx86() : NvccCompilerOptions.Createx64();
                    opt.CompileMode = compileMode;
                    CompilerOptionsList.Add(opt);
                }
                bool binary = (compileMode & eCudafyCompileMode.Binary) == eCudafyCompileMode.Binary;
                // Write to temp file
                string tempFileName = "CUDAFYSOURCETEMP.tmp";
                string cuFileName = WorkingDirectory + Path.DirectorySeparatorChar + tempFileName.Replace(".tmp", ".cu");
                string ptxFileName = WorkingDirectory + Path.DirectorySeparatorChar + tempFileName.Replace(".tmp", binary ? ".cubin" : ".ptx");
                File.WriteAllText(cuFileName, SourceCode, Encoding.Default);

                foreach (CompilerOptions co in CompilerOptionsList)
                {
                    co.GenerateDebugInfo = GenerateDebug;
                    co.TimeOut = TimeOut;
                    co.ClearSources();
                    co.AddSource(cuFileName);

                    co.ClearOutputs();
                    co.AddOutput(ptxFileName);

                    CompilerOutput += "\r\n" + co.GetSummary();
                    CompilerOutput += "\r\n" + co.GetArguments();

                    // Convert to ptx
                    Process process = new Process();
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError = true;
                    process.StartInfo.CreateNoWindow = SuppressWindow;//WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                    process.StartInfo.FileName = co.GetFileName();
                    process.StartInfo.Arguments = co.GetArguments();
                    CompilerArguments = process.StartInfo.Arguments;
                    process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
                    process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
                    Debug.WriteLine(process.StartInfo.FileName);
                    Debug.WriteLine(CompilerArguments);
                    standardError.Clear(); standardOutput.Clear();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();
                    process.Start();
                    

                    //while (!process.HasExited)
                    //    Thread.Sleep(10);
                    int waitCounter = 0;
                    bool procTimedOut = false;
                    int timeout = co.TimeOut;
                    while (!process.HasExited && !(procTimedOut = ++waitCounter >= timeout)) // 1m timeout
                        //Thread.Sleep(10);
                        process.WaitForExit(10);
                    if (procTimedOut)
                        throw new CudafyCompileException(CudafyCompileException.csCOMPILATION_ERROR_X, "Process timed out");

                    if (process.ExitCode != 0)
                    {
                        string s = standardError.ToString(); //process.StandardError.ReadToEnd();
                        
                        CompilerOutput += "\r\n" + s;
                        if (s.Contains("Cannot find compiler 'cl.exe' in PATH"))
                            CompilerOutput += "\r\nPlease add the Visual Studio VC bin directory to PATH in Environment Variables.";
                        Debug.WriteLine(s);
                        throw new CudafyCompileException(CudafyCompileException.csCOMPILATION_ERROR_X, s);
                    }
                    else
                    {
                        string s = standardError.ToString() + "\r\n" + standardOutput.ToString();
                        CompilerOutput += "\r\n" + s;
                        Debug.WriteLine(s);
                    }

                    // Load ptx file
                    if ((compileMode & eCudafyCompileMode.Binary) == eCudafyCompileMode.Binary)
                        this.StoreBinaryFile("na", co.Platform, co.Architecture, ptxFileName);                        
                    else
                        this.StorePTXFile("na", co.Platform, co.Architecture, ptxFileName);
#if DEBUG

#else
                    if (deleteGeneratedCode)
                        Delete(cuFileName, ptxFileName);
#endif
                }
            }
            return CompilerArguments;
        }