internal static async Task Build(string sourceDir, string outputFile, Nuget.Repository repository)
        {
            string outputDir = Path.GetDirectoryName(outputFile);

            var sourceFiles = new DirectoryInfo(sourceDir).GetFiles("*.*", SearchOption.AllDirectories);

            var metaData = GetMetaData(sourceFiles);

            var nugetSources = metaData[nugetSourceKeyWord].Distinct()
                               .Select(Nuget.GetSource)
                               .ToList();

            if (!nugetSources.Any())
            {
                nugetSources = new List <Nuget.ISource> {
                    Nuget.GetDefaultSource()
                };
            }

            var nugetPackages = metaData[nugetPackageKeyWord].Distinct().ToList();

            var installedNugetPackages = await repository.EnsurePackagesAreInstalled(nugetSources, nugetPackages);

            // compile
            var csharpProvider = new Microsoft.CSharp.CSharpCodeProvider();

            var externalReferences = installedNugetPackages.SelectMany(_ => _.GetReferenceAssemblies()).ToArray();

            foreach (var i in externalReferences)
            {
                Copy(i, Path.Combine(outputDir, Path.GetFileName(i)));
            }

            var internalReferences = new[] {
                "System.Runtime.dll",
                "System.dll",
                "System.Xml.dll",
                "Microsoft.CSharp.dll",
                "System.Core.dll",
            };

            var options = new CompilerParameters()
            {
                OutputAssembly          = outputFile,
                GenerateExecutable      = true,
                IncludeDebugInformation = false,
                GenerateInMemory        = false,
                MainClass = "Program",
            };

            options.ReferencedAssemblies.AddRange(internalReferences.Concat(externalReferences).ToArray());

            var results = csharpProvider.CompileAssemblyFromFile(options, sourceFiles.Where(Util.IsCSharpFile).Select(_ => _.FullName).ToArray());

            if (results.Errors.Cast <object>().Any())
            {
                var s = String.Join("\r\n", results.Errors.Cast <object>().ToArray());
                throw new Exception(s);
            }
        }
        public SelfCompilingExecutable(string executable, string cacheRoot = null)
        {
            if (cacheRoot == null)
            {
                cacheRoot = Path.Combine(Path.GetTempPath(), "sce");
            }

            this.executable = Path.GetFullPath(executable);
            this.cacheDir   = Path.Combine(cacheRoot, Util.GetDigest(this.executable));
            this.sourceDir  = this.executable + ".src";
            repository      = new Nuget.Repository(Path.Combine(cacheRoot, "packages"));
            FS.EnsureDirectoryExists(this.cacheDir);
        }