public static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, string toolsVersion, string file)
        {
            lock (builders) {
                var    toolsFx = Runtime.SystemAssemblyService.GetTargetFramework(new TargetFrameworkMoniker(toolsVersion));
                string binDir  = runtime.GetMSBuildBinPath(toolsFx);

                if (!runtime.IsInstalled(toolsFx))
                {
                    throw new InvalidOperationException(string.Format(
                                                            "Runtime '{0}' does not have the MSBuild '{1}' framework installed",
                                                            runtime.Id, toolsVersion));
                }

                string            builderKey = runtime.Id + " " + toolsVersion;
                RemoteBuildEngine builder;
                if (builders.TryGetValue(builderKey, out builder))
                {
                    builder.ReferenceCount++;
                    return(new RemoteProjectBuilder(file, binDir, builder));
                }


                //always start the remote process explicitly, even if it's using the current runtime and fx
                //else it won't pick up the assembly redirects from the builder exe
                var exe = GetExeLocation(toolsVersion);
                MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel();
                var pinfo = new ProcessStartInfo(exe)
                {
                    UseShellExecute       = false,
                    CreateNoWindow        = true,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                };
                runtime.GetToolsExecutionEnvironment(toolsFx).MergeTo(pinfo);

                Process p = null;
                try {
                    p = runtime.ExecuteAssembly(pinfo);
                    p.StandardInput.WriteLine(Process.GetCurrentProcess().Id.ToString());
                    string          sref = p.StandardError.ReadLine();
                    byte[]          data = Convert.FromBase64String(sref);
                    MemoryStream    ms   = new MemoryStream(data);
                    BinaryFormatter bf   = new BinaryFormatter();
                    builder = new RemoteBuildEngine(p, (IBuildEngine)bf.Deserialize(ms));
                } catch {
                    if (p != null)
                    {
                        try {
                            p.Kill();
                        } catch { }
                    }
                    throw;
                }

                builders [builderKey]  = builder;
                builder.ReferenceCount = 1;
                return(new RemoteProjectBuilder(file, binDir, builder));
            }
        }
예제 #2
0
        public static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, TargetFramework fx, string file)
        {
            lock (builders) {
                string binDir = runtime.GetMSBuildBinPath(fx);

                RemoteBuildEngine builder;
                if (builders.TryGetValue(runtime, out builder))
                {
                    builder.ReferenceCount++;
                    return(new RemoteProjectBuilder(file, binDir, builder));
                }

                if (runtime.IsRunning)
                {
                    if (currentBuildEngine == null)
                    {
                        currentBuildEngine = new RemoteBuildEngine(null, new BuildEngine());
                    }
                    return(new RemoteProjectBuilder(file, binDir, currentBuildEngine));
                }
                else
                {
                    MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel();
                    string           exe   = typeof(ProjectBuilder).Assembly.Location;
                    ProcessStartInfo pinfo = new ProcessStartInfo(exe);
                    runtime.GetToolsExecutionEnvironment(fx).MergeTo(pinfo);
                    pinfo.UseShellExecute       = false;
                    pinfo.RedirectStandardError = true;
                    pinfo.RedirectStandardInput = true;

                    Process p = null;
                    try {
                        p = runtime.ExecuteAssembly(pinfo, fx);
                        p.StandardInput.WriteLine(Process.GetCurrentProcess().Id.ToString());
                        string          sref = p.StandardError.ReadLine();
                        byte[]          data = Convert.FromBase64String(sref);
                        MemoryStream    ms   = new MemoryStream(data);
                        BinaryFormatter bf   = new BinaryFormatter();
                        builder = new RemoteBuildEngine(p, (IBuildEngine)bf.Deserialize(ms));
                    } catch {
                        if (p != null)
                        {
                            try {
                                p.Kill();
                            } catch { }
                        }
                        throw;
                    }
                }
                builders [runtime]     = builder;
                builder.ReferenceCount = 1;
                return(new RemoteProjectBuilder(file, binDir, builder));
            }
        }
예제 #3
0
        internal static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, string minToolsVersion, string file, string solutionFile)
        {
            lock (builders) {
                //attempt to use 12.0 builder first if available
                string toolsVersion = "12.0";
                string binDir       = runtime.GetMSBuildBinPath("12.0");
                if (binDir == null)
                {
                    //fall back to 4.0, we know it's always available
                    toolsVersion = "4.0";
                }

                //check the ToolsVersion we found can handle the project
                Version tv, mtv;
                if (Version.TryParse(toolsVersion, out tv) && Version.TryParse(minToolsVersion, out mtv) && tv < mtv)
                {
                    string error = null;
                    if (runtime is MsNetTargetRuntime && minToolsVersion == "12.0")
                    {
                        error = "MSBuild 2013 is not installed. Please download and install it from " +
                                "http://www.microsoft.com/en-us/download/details.aspx?id=40760";
                    }
                    throw new InvalidOperationException(error ?? string.Format(
                                                            "Runtime '{0}' does not have MSBuild '{1}' ToolsVersion installed",
                                                            runtime.Id, toolsVersion)
                                                        );
                }

                //one builder per solution
                string            builderKey = runtime.Id + " # " + solutionFile;
                RemoteBuildEngine builder;
                if (builders.TryGetValue(builderKey, out builder))
                {
                    builder.ReferenceCount++;
                    return(new RemoteProjectBuilder(file, builder));
                }

                //always start the remote process explicitly, even if it's using the current runtime and fx
                //else it won't pick up the assembly redirects from the builder exe
                var exe = GetExeLocation(runtime, toolsVersion);
                MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel();
                var pinfo = new ProcessStartInfo(exe)
                {
                    UseShellExecute       = false,
                    CreateNoWindow        = true,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                };
                runtime.GetToolsExecutionEnvironment().MergeTo(pinfo);

                Process p = null;
                try {
                    p = runtime.ExecuteAssembly(pinfo);
                    p.StandardInput.WriteLine(Process.GetCurrentProcess().Id.ToString());
                    string responseKey = "[MonoDevelop]";
                    string sref;
                    while (true)
                    {
                        sref = p.StandardError.ReadLine();
                        if (sref.StartsWith(responseKey, StringComparison.Ordinal))
                        {
                            sref = sref.Substring(responseKey.Length);
                            break;
                        }
                    }
                    byte[]          data   = Convert.FromBase64String(sref);
                    MemoryStream    ms     = new MemoryStream(data);
                    BinaryFormatter bf     = new BinaryFormatter();
                    var             engine = (IBuildEngine)bf.Deserialize(ms);
                    engine.SetCulture(GettextCatalog.UICulture);
                    engine.SetGlobalProperties(GetCoreGlobalProperties(solutionFile));
                    foreach (var gpp in globalPropertyProviders)
                    {
                        builder.SetGlobalProperties(gpp.GetGlobalProperties());
                    }
                    builder = new RemoteBuildEngine(p, engine);
                } catch {
                    if (p != null)
                    {
                        try {
                            p.Kill();
                        } catch { }
                    }
                    throw;
                }

                builders [builderKey]  = builder;
                builder.ReferenceCount = 1;
                return(new RemoteProjectBuilder(file, builder));
            }
        }
        public static BuildResult Compile(ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, IProgressMonitor monitor)
        {
            CSharpCompilerParameters compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters();
            CSharpProjectParameters  projectParameters  = (CSharpProjectParameters)configuration.ProjectParameters ?? new CSharpProjectParameters();

            string outputName       = configuration.CompiledOutputName;
            string responseFileName = Path.GetTempFileName();

            TargetRuntime runtime = MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime;
            DotNetProject project = configuration.ParentItem as DotNetProject;

            if (project != null)
            {
                runtime = project.TargetRuntime;
            }

            StringBuilder sb       = new StringBuilder();
            List <string> gacRoots = new List <string> ();

            sb.AppendFormat("\"/out:{0}\"", outputName);
            sb.AppendLine();

            HashSet <string> alreadyAddedReference = new HashSet <string> ();

            foreach (ProjectReference lib in projectItems.GetAll <ProjectReference> ())
            {
                if (lib.ReferenceType == ReferenceType.Project && !(lib.OwnerProject.ParentSolution.FindProjectByName(lib.Reference) is DotNetProject))
                {
                    continue;
                }
                foreach (string fileName in lib.GetReferencedFileNames(configSelector))
                {
                    switch (lib.ReferenceType)
                    {
                    case ReferenceType.Gac:
                        SystemPackage pkg = lib.Package;
                        if (pkg == null)
                        {
                            string msg = string.Format(GettextCatalog.GetString("{0} could not be found or is invalid."), lib.Reference);
                            monitor.ReportWarning(msg);
                            continue;
                        }

                        if (alreadyAddedReference.Add(fileName))
                        {
                            AppendQuoted(sb, "/r:", fileName);
                        }

                        if (pkg.GacRoot != null && !gacRoots.Contains(pkg.GacRoot))
                        {
                            gacRoots.Add(pkg.GacRoot);
                        }
                        if (!string.IsNullOrEmpty(pkg.Requires))
                        {
                            foreach (string requiredPackage in pkg.Requires.Split(' '))
                            {
                                SystemPackage rpkg = runtime.AssemblyContext.GetPackage(requiredPackage);
                                if (rpkg == null)
                                {
                                    continue;
                                }
                                foreach (SystemAssembly assembly in rpkg.Assemblies)
                                {
                                    if (alreadyAddedReference.Add(assembly.Location))
                                    {
                                        AppendQuoted(sb, "/r:", assembly.Location);
                                    }
                                }
                            }
                        }
                        break;

                    default:
                        if (alreadyAddedReference.Add(fileName))
                        {
                            AppendQuoted(sb, "/r:", fileName);
                        }
                        break;
                    }
                }
            }

            sb.AppendLine("/nologo");
            sb.Append("/warn:"); sb.Append(compilerParameters.WarningLevel.ToString());
            sb.AppendLine();

            if (configuration.SignAssembly)
            {
                if (File.Exists(configuration.AssemblyKeyFile))
                {
                    AppendQuoted(sb, "/keyfile:", configuration.AssemblyKeyFile);
                }
            }

            if (configuration.DebugMode)
            {
                sb.AppendLine("/debug:+");
                sb.AppendLine("/debug:full");
            }

            switch (compilerParameters.LangVersion)
            {
            case LangVersion.Default:
                break;

            case LangVersion.ISO_1:
                sb.AppendLine("/langversion:ISO-1");
                break;

            case LangVersion.ISO_2:
                sb.AppendLine("/langversion:ISO-2");
                break;

            default:
                string message = "Invalid LangVersion enum value '" + compilerParameters.LangVersion.ToString() + "'";
                monitor.ReportError(message, null);
                LoggingService.LogError(message);
                return(null);
            }

            // mcs default is + but others might not be
            if (compilerParameters.Optimize)
            {
                sb.AppendLine("/optimize+");
            }
            else
            {
                sb.AppendLine("/optimize-");
            }

            bool hasWin32Res = !string.IsNullOrEmpty(projectParameters.Win32Resource) && File.Exists(projectParameters.Win32Resource);

            if (hasWin32Res)
            {
                AppendQuoted(sb, "/win32res:", projectParameters.Win32Resource);
            }

            if (!string.IsNullOrEmpty(projectParameters.Win32Icon) && File.Exists(projectParameters.Win32Icon))
            {
                if (hasWin32Res)
                {
                    monitor.ReportWarning("Both Win32 icon and Win32 resource cannot be specified. Ignoring the icon.");
                }
                else
                {
                    AppendQuoted(sb, "/win32icon:", projectParameters.Win32Icon);
                }
            }

            if (projectParameters.CodePage != 0)
            {
                sb.AppendLine("/codepage:" + projectParameters.CodePage);
            }
            else if (runtime is MonoTargetRuntime)
            {
                sb.AppendLine("/codepage:utf8");
            }

            if (compilerParameters.UnsafeCode)
            {
                sb.AppendLine("-unsafe");
            }
            if (compilerParameters.NoStdLib)
            {
                sb.AppendLine("-nostdlib");
            }

            if (!string.IsNullOrEmpty(compilerParameters.PlatformTarget) && compilerParameters.PlatformTarget.ToLower() != "anycpu")
            {
                //HACK: to ignore the platform flag for Mono <= 2.4, because gmcs didn't support it
                if (runtime.RuntimeId == "Mono" && runtime.AssemblyContext.GetAssemblyLocation("Mono.Debugger.Soft", null) == null)
                {
                    LoggingService.LogWarning("Mono runtime '" + runtime.DisplayName +
                                              "' appears to be too old to support the 'platform' C# compiler flag.");
                }
                else
                {
                    sb.AppendLine("/platform:" + compilerParameters.PlatformTarget);
                }
            }

            if (compilerParameters.TreatWarningsAsErrors)
            {
                sb.AppendLine("-warnaserror");
                if (!string.IsNullOrEmpty(compilerParameters.WarningsNotAsErrors))
                {
                    sb.AppendLine("-warnaserror-:" + compilerParameters.WarningsNotAsErrors);
                }
            }

            if (compilerParameters.DefineSymbols.Length > 0)
            {
                string define_str = string.Join(";", compilerParameters.DefineSymbols.Split(new char [] { ',', ' ', ';' }, StringSplitOptions.RemoveEmptyEntries));
                if (define_str.Length > 0)
                {
                    AppendQuoted(sb, "/define:", define_str);
                    sb.AppendLine();
                }
            }

            CompileTarget ctarget = configuration.CompileTarget;

            if (!string.IsNullOrEmpty(projectParameters.MainClass))
            {
                sb.AppendLine("/main:" + projectParameters.MainClass);
                // mcs does not allow providing a Main class when compiling a dll
                // As a workaround, we compile as WinExe (although the output will still
                // have a .dll extension).
                if (ctarget == CompileTarget.Library)
                {
                    ctarget = CompileTarget.WinExe;
                }
            }

            switch (ctarget)
            {
            case CompileTarget.Exe:
                sb.AppendLine("/t:exe");
                break;

            case CompileTarget.WinExe:
                sb.AppendLine("/t:winexe");
                break;

            case CompileTarget.Library:
                sb.AppendLine("/t:library");
                break;
            }

            foreach (ProjectFile finfo in projectItems.GetAll <ProjectFile> ())
            {
                if (finfo.Subtype == Subtype.Directory)
                {
                    continue;
                }

                switch (finfo.BuildAction)
                {
                case "Compile":
                    AppendQuoted(sb, "", finfo.Name);
                    break;

                case "EmbeddedResource":
                    string fname = finfo.Name;
                    if (string.Compare(Path.GetExtension(fname), ".resx", true) == 0)
                    {
                        fname = Path.ChangeExtension(fname, ".resources");
                    }
                    sb.Append('"'); sb.Append("/res:");
                    sb.Append(fname); sb.Append(','); sb.Append(finfo.ResourceId);
                    sb.Append('"'); sb.AppendLine();
                    break;

                default:
                    continue;
                }
            }
            if (compilerParameters.GenerateXmlDocumentation)
            {
                AppendQuoted(sb, "/doc:", Path.ChangeExtension(outputName, ".xml"));
            }

            if (!string.IsNullOrEmpty(compilerParameters.AdditionalArguments))
            {
                sb.AppendLine(compilerParameters.AdditionalArguments);
            }

            if (!string.IsNullOrEmpty(compilerParameters.NoWarnings))
            {
                AppendQuoted(sb, "/nowarn:", compilerParameters.NoWarnings);
            }

            if (runtime.RuntimeId == "MS.NET")
            {
                sb.AppendLine("/fullpaths");
                sb.AppendLine("/utf8output");
            }

            string output = "";
            string error  = "";

            File.WriteAllText(responseFileName, sb.ToString());

            string compilerName;

            try {
                compilerName = GetCompilerName(runtime, configuration.TargetFramework);
            } catch (Exception e) {
                string message = "Could not obtain a C# compiler";
                monitor.ReportError(message, e);
                return(null);
            }

            monitor.Log.WriteLine(compilerName + " /noconfig " + sb.ToString().Replace('\n', ' '));

            string workingDir = ".";

            if (configuration.ParentItem != null)
            {
                workingDir = configuration.ParentItem.BaseDirectory;
                if (workingDir == null)
                {
                    // Dummy projects created for single files have no filename
                    // and so no BaseDirectory.
                    // This is a workaround for a bug in
                    // ProcessStartInfo.WorkingDirectory - not able to handle null
                    workingDir = ".";
                }
            }

            LoggingService.LogInfo(compilerName + " " + sb.ToString());

            ExecutionEnvironment envVars = runtime.GetToolsExecutionEnvironment(project.TargetFramework);
            string cargs = "/noconfig @\"" + responseFileName + "\"";

            int exitCode = DoCompilation(compilerName, cargs, workingDir, envVars, gacRoots, ref output, ref error);

            BuildResult result = ParseOutput(output, error);

            if (result.CompilerOutput.Trim().Length != 0)
            {
                monitor.Log.WriteLine(result.CompilerOutput);
            }

            //if compiler crashes, output entire error string
            if (result.ErrorCount == 0 && exitCode != 0)
            {
                try {
                    monitor.Log.Write(File.ReadAllText(error));
                } catch (IOException) {
                }
                result.AddError("The compiler appears to have crashed. Check the build output pad for details.");
                LoggingService.LogError("C# compiler crashed. Response file '{0}', stdout file '{1}', stderr file '{2}'",
                                        responseFileName, output, error);
            }
            else
            {
                FileService.DeleteFile(responseFileName);
                FileService.DeleteFile(output);
                FileService.DeleteFile(error);
            }
            return(result);
        }
예제 #5
0
        public static BuildResult Compile(ProjectItemCollection projectItems, DotNetProjectConfiguration configuration, ConfigurationSelector configSelector, ProgressMonitor monitor)
        {
            var compilerParameters = (CSharpCompilerParameters)configuration.CompilationParameters ?? new CSharpCompilerParameters();
            var projectParameters  = (CSharpProject)configuration.ParentItem;

            FilePath outputName       = configuration.CompiledOutputName;
            string   responseFileName = Path.GetTempFileName();

            //make sure that the output file is writable
            if (File.Exists(outputName))
            {
                bool isWriteable = false;
                int  count       = 0;
                do
                {
                    try {
                        outputName.MakeWritable();
                        using (var stream = File.OpenWrite(outputName)) {
                            isWriteable = true;
                        }
                    } catch (Exception) {
                        Thread.Sleep(20);
                    }
                } while (count++ < 5 && !isWriteable);
                if (!isWriteable)
                {
                    MessageService.ShowError(string.Format(GettextCatalog.GetString("Can't lock file: {0}."), outputName));
                    return(null);
                }
            }

            //get the runtime
            TargetRuntime runtime = MonoDevelop.Core.Runtime.SystemAssemblyService.DefaultRuntime;
            DotNetProject project = configuration.ParentItem as DotNetProject;

            if (project != null)
            {
                runtime = project.TargetRuntime;
            }

            //get the compiler name
            string compilerName;

            try {
                compilerName = GetCompilerName(runtime, configuration.TargetFramework);
            } catch (Exception e) {
                string message = "Could not obtain a C# compiler";
                monitor.ReportError(message, e);
                return(null);
            }

            var sb = new StringBuilder();

            HashSet <string> alreadyAddedReference = new HashSet <string> ();

            var monoRuntime = runtime as MonoTargetRuntime;

            if (!compilerParameters.NoStdLib && (monoRuntime == null || monoRuntime.HasMultitargetingMcs))
            {
                string corlib = project.AssemblyContext.GetAssemblyFullName("mscorlib", project.TargetFramework);
                if (corlib != null)
                {
                    corlib = project.AssemblyContext.GetAssemblyLocation(corlib, project.TargetFramework);
                }
                if (corlib == null)
                {
                    var br = new BuildResult();
                    br.AddError(string.Format("Could not find mscorlib for framework {0}", project.TargetFramework.Id));
                    return(br);
                }
                AppendQuoted(sb, "/r:", corlib);
                sb.AppendLine("-nostdlib");
            }

            List <string> gacRoots = new List <string> ();

            sb.AppendFormat("\"/out:{0}\"", outputName);
            sb.AppendLine();

            foreach (ProjectReference lib in projectItems.GetAll <ProjectReference> ())
            {
                if (lib.ReferenceType == ReferenceType.Project)
                {
                    var ownerProject = lib.OwnerProject;
                    if (ownerProject != null)
                    {
                        var parentSolution = ownerProject.ParentSolution;
                        if (parentSolution != null && !(lib.ResolveProject(parentSolution) is DotNetProject))
                        {
                            continue;
                        }
                    }
                }
                string refPrefix = string.IsNullOrEmpty(lib.Aliases) ? "" : lib.Aliases + "=";
                foreach (string fileName in lib.GetReferencedFileNames(configSelector))
                {
                    switch (lib.ReferenceType)
                    {
                    case ReferenceType.Package:
                        SystemPackage pkg = lib.Package;
                        if (pkg == null)
                        {
                            string msg = string.Format(GettextCatalog.GetString("{0} could not be found or is invalid."), lib.Reference);
                            monitor.ReportWarning(msg);
                            continue;
                        }

                        if (alreadyAddedReference.Add(fileName))
                        {
                            AppendQuoted(sb, "/r:", refPrefix + fileName);
                        }

                        if (pkg.GacRoot != null && !gacRoots.Contains(pkg.GacRoot))
                        {
                            gacRoots.Add(pkg.GacRoot);
                        }
                        if (!string.IsNullOrEmpty(pkg.Requires))
                        {
                            foreach (string requiredPackage in pkg.Requires.Split(' '))
                            {
                                SystemPackage rpkg = runtime.AssemblyContext.GetPackage(requiredPackage);
                                if (rpkg == null)
                                {
                                    continue;
                                }
                                foreach (SystemAssembly assembly in rpkg.Assemblies)
                                {
                                    if (alreadyAddedReference.Add(assembly.Location))
                                    {
                                        AppendQuoted(sb, "/r:", assembly.Location);
                                    }
                                }
                            }
                        }
                        break;

                    default:
                        if (alreadyAddedReference.Add(fileName))
                        {
                            AppendQuoted(sb, "/r:", refPrefix + fileName);
                        }
                        break;
                    }
                }
            }

            if (alreadyAddedReference.Any(reference => SystemAssemblyService.ContainsReferenceToSystemRuntime(reference)))
            {
                LoggingService.LogInfo("Found PCLv2 assembly.");
                var facades = runtime.FindFacadeAssembliesForPCL(project.TargetFramework);
                foreach (var facade in facades)
                {
                    AppendQuoted(sb, "/r:", facade);
                }
            }

            string sysCore = project.AssemblyContext.GetAssemblyFullName("System.Core", project.TargetFramework);

            if (sysCore != null && !alreadyAddedReference.Contains(sysCore))
            {
                var asm = project.AssemblyContext.GetAssemblyFromFullName(sysCore, null, project.TargetFramework);
                if (asm != null)
                {
                    AppendQuoted(sb, "/r:", asm.Location);
                }
            }

            sb.AppendLine("/nologo");
            sb.Append("/warn:"); sb.Append(compilerParameters.WarningLevel.ToString());
            sb.AppendLine();

            if (configuration.SignAssembly)
            {
                if (File.Exists(configuration.AssemblyKeyFile))
                {
                    AppendQuoted(sb, "/keyfile:", configuration.AssemblyKeyFile);
                }
                if (configuration.DelaySign)
                {
                    sb.AppendLine("/delaySign");
                }
            }

            var debugType = configuration.DebugType;

            if (string.IsNullOrEmpty(debugType))
            {
                debugType = configuration.DebugSymbols ? "full" : "none";
            }
            else if (string.Equals(debugType, "pdbonly", StringComparison.OrdinalIgnoreCase))
            {
                //old Mono compilers don't support pdbonly
                if (monoRuntime != null && !monoRuntime.HasMultitargetingMcs)
                {
                    debugType = "full";
                }
            }
            if (!string.Equals(debugType, "none", StringComparison.OrdinalIgnoreCase))
            {
                sb.AppendLine("/debug:" + debugType);
            }

            if (compilerParameters.LangVersion != LangVersion.Default)
            {
                var langVersionString = CSharpCompilerParameters.TryLangVersionToString(compilerParameters.LangVersion);
                if (langVersionString == null)
                {
                    string message = "Invalid LangVersion enum value '" + compilerParameters.LangVersion.ToString() + "'";
                    monitor.ReportError(message, null);
                    LoggingService.LogError(message);
                    return(null);
                }
                sb.AppendLine("/langversion:" + langVersionString);
            }

            // mcs default is + but others might not be
            if (compilerParameters.Optimize)
            {
                sb.AppendLine("/optimize+");
            }
            else
            {
                sb.AppendLine("/optimize-");
            }

            bool hasWin32Res = !string.IsNullOrEmpty(projectParameters.Win32Resource) && File.Exists(projectParameters.Win32Resource);

            if (hasWin32Res)
            {
                AppendQuoted(sb, "/win32res:", projectParameters.Win32Resource);
            }

            if (!string.IsNullOrEmpty(projectParameters.Win32Icon) && File.Exists(projectParameters.Win32Icon))
            {
                if (hasWin32Res)
                {
                    monitor.ReportWarning("Both Win32 icon and Win32 resource cannot be specified. Ignoring the icon.");
                }
                else
                {
                    AppendQuoted(sb, "/win32icon:", projectParameters.Win32Icon);
                }
            }

            if (projectParameters.CodePage != 0)
            {
                sb.AppendLine("/codepage:" + projectParameters.CodePage);
            }
            else if (runtime is MonoTargetRuntime)
            {
                sb.AppendLine("/codepage:utf8");
            }

            if (compilerParameters.UnsafeCode)
            {
                sb.AppendLine("-unsafe");
            }
            if (compilerParameters.NoStdLib)
            {
                sb.AppendLine("-nostdlib");
            }

            if (!string.IsNullOrEmpty(compilerParameters.PlatformTarget) && compilerParameters.PlatformTarget.ToLower() != "anycpu")
            {
                //HACK: to ignore the platform flag for Mono <= 2.4, because gmcs didn't support it
                if (runtime.RuntimeId == "Mono" && runtime.AssemblyContext.GetAssemblyLocation("Mono.Debugger.Soft", null) == null)
                {
                    LoggingService.LogWarning("Mono runtime '" + runtime.DisplayName +
                                              "' appears to be too old to support the 'platform' C# compiler flag.");
                }
                else
                {
                    sb.AppendLine("/platform:" + compilerParameters.PlatformTarget);
                }
            }

            if (compilerParameters.TreatWarningsAsErrors)
            {
                sb.AppendLine("-warnaserror");
                if (!string.IsNullOrEmpty(compilerParameters.WarningsNotAsErrors))
                {
                    sb.AppendLine("-warnaserror-:" + compilerParameters.WarningsNotAsErrors);
                }
            }

            foreach (var define in configuration.GetDefineSymbols())
            {
                AppendQuoted(sb, "/define:", define);
                sb.AppendLine();
            }

            CompileTarget ctarget = configuration.CompileTarget;

            if (!string.IsNullOrEmpty(projectParameters.MainClass))
            {
                sb.AppendLine("/main:" + projectParameters.MainClass);
                // mcs does not allow providing a Main class when compiling a dll
                // As a workaround, we compile as WinExe (although the output will still
                // have a .dll extension).
                if (ctarget == CompileTarget.Library)
                {
                    ctarget = CompileTarget.WinExe;
                }
            }

            switch (ctarget)
            {
            case CompileTarget.Exe:
                sb.AppendLine("/t:exe");
                break;

            case CompileTarget.WinExe:
                sb.AppendLine("/t:winexe");
                break;

            case CompileTarget.Library:
                sb.AppendLine("/t:library");
                break;
            }

            foreach (ProjectFile finfo in projectItems.GetAll <ProjectFile> ())
            {
                if (finfo.Subtype == Subtype.Directory)
                {
                    continue;
                }

                switch (finfo.BuildAction)
                {
                case "Compile":
                    AppendQuoted(sb, "", finfo.Name);
                    break;

                case "EmbeddedResource":
                    string fname = finfo.Name;
                    if (string.Compare(Path.GetExtension(fname), ".resx", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        fname = Path.ChangeExtension(fname, ".resources");
                    }
                    sb.Append('"'); sb.Append("/res:");
                    sb.Append(fname); sb.Append(','); sb.Append(finfo.ResourceId);
                    sb.Append('"'); sb.AppendLine();
                    break;

                default:
                    continue;
                }
            }
            if (!compilerParameters.DocumentationFile.IsNullOrEmpty)
            {
                AppendQuoted(sb, "/doc:", compilerParameters.DocumentationFile);
            }

            if (!string.IsNullOrEmpty(compilerParameters.NoWarnings))
            {
                AppendQuoted(sb, "/nowarn:", compilerParameters.NoWarnings);
            }

            if (runtime.RuntimeId == "MS.NET")
            {
                sb.AppendLine("/fullpaths");
                sb.AppendLine("/utf8output");
            }

            string output = "";
            string error  = "";

            File.WriteAllText(responseFileName, sb.ToString());

            monitor.Log.WriteLine(compilerName + " /noconfig " + sb.ToString().Replace('\n', ' '));

            // Dummy projects created for single files have no filename
            // and so no BaseDirectory.
            string workingDir = null;

            if (configuration.ParentItem != null)
            {
                workingDir = configuration.ParentItem.BaseDirectory;
            }

            LoggingService.LogInfo(compilerName + " " + sb);

            ExecutionEnvironment envVars = runtime.GetToolsExecutionEnvironment(project.TargetFramework);
            string cargs = "/noconfig @\"" + responseFileName + "\"";

            int exitCode = DoCompilation(monitor, compilerName, cargs, workingDir, envVars, gacRoots, ref output, ref error);

            BuildResult result = ParseOutput(workingDir, output, error);

            if (result.CompilerOutput.Trim().Length != 0)
            {
                monitor.Log.WriteLine(result.CompilerOutput);
            }

            //if compiler crashes, output entire error string
            if (result.ErrorCount == 0 && exitCode != 0)
            {
                try {
                    monitor.Log.Write(File.ReadAllText(error));
                } catch (IOException) {
                }
                result.AddError("The compiler appears to have crashed. Check the build output pad for details.");
                LoggingService.LogError("C# compiler crashed. Response file '{0}', stdout file '{1}', stderr file '{2}'",
                                        responseFileName, output, error);
            }
            else
            {
                FileService.DeleteFile(responseFileName);
                FileService.DeleteFile(output);
                FileService.DeleteFile(error);
            }
            return(result);
        }
예제 #6
0
        public static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, string toolsVersion, string file, string solutionFile)
        {
            lock (builders) {
                string binDir = runtime.GetMSBuildBinPath(toolsVersion);
                if (binDir == null)
                {
                    string error = null;
                    if (runtime is MsNetTargetRuntime)
                    {
                        if (toolsVersion == "12.0")
                        {
                            error = "MSBuild 2013 is not installed. Please download and install it from " +
                                    "http://www.microsoft.com/en-us/download/details.aspx?id=40760";
                        }
                    }
                    ;
                    throw new InvalidOperationException(error ?? string.Format(
                                                            "Runtime '{0}' does not have MSBuild '{1}' ToolsVersion installed",
                                                            runtime.Id, toolsVersion)
                                                        );
                }

                string            builderKey = runtime.Id + " " + toolsVersion;
                RemoteBuildEngine builder;
                if (builders.TryGetValue(builderKey, out builder))
                {
                    builder.ReferenceCount++;
                    return(new RemoteProjectBuilder(file, solutionFile, binDir, builder));
                }

                //always start the remote process explicitly, even if it's using the current runtime and fx
                //else it won't pick up the assembly redirects from the builder exe
                var exe = GetExeLocation(runtime, toolsVersion);
                MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel();
                var pinfo = new ProcessStartInfo(exe)
                {
                    UseShellExecute       = false,
                    CreateNoWindow        = true,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                };
                runtime.GetToolsExecutionEnvironment().MergeTo(pinfo);

                Process p = null;
                try {
                    p = runtime.ExecuteAssembly(pinfo);
                    p.StandardInput.WriteLine(Process.GetCurrentProcess().Id.ToString());
                    string          sref   = p.StandardError.ReadLine();
                    byte[]          data   = Convert.FromBase64String(sref);
                    MemoryStream    ms     = new MemoryStream(data);
                    BinaryFormatter bf     = new BinaryFormatter();
                    var             engine = (IBuildEngine)bf.Deserialize(ms);
                    engine.SetUICulture(GettextCatalog.UICulture);
                    builder = new RemoteBuildEngine(p, engine);
                } catch {
                    if (p != null)
                    {
                        try {
                            p.Kill();
                        } catch { }
                    }
                    throw;
                }

                builders [builderKey]  = builder;
                builder.ReferenceCount = 1;
                return(new RemoteProjectBuilder(file, solutionFile, binDir, builder));
            }
        }
예제 #7
0
        internal static RemoteProjectBuilder GetProjectBuilder(TargetRuntime runtime, string minToolsVersion, string file, string solutionFile)
        {
            lock (builders) {
                //attempt to use 14.0 builder first if available
                string toolsVersion = "14.0";
                string binDir       = runtime.GetMSBuildBinPath("14.0");
                if (binDir == null)
                {
                    toolsVersion = "12.0";
                    binDir       = runtime.GetMSBuildBinPath("12.0");
                    if (binDir == null)
                    {
                        //fall back to 4.0, we know it's always available
                        toolsVersion = "4.0";
                    }
                }

                //check the ToolsVersion we found can handle the project
                Version tv, mtv;
                if (Version.TryParse(toolsVersion, out tv) && Version.TryParse(minToolsVersion, out mtv) && tv < mtv)
                {
                    string error = null;
                    if (runtime is MsNetTargetRuntime && minToolsVersion == "12.0")
                    {
                        error = "MSBuild 2013 is not installed. Please download and install it from " +
                                "http://www.microsoft.com/en-us/download/details.aspx?id=40760";
                    }
                    throw new InvalidOperationException(error ?? string.Format(
                                                            "Runtime '{0}' does not have MSBuild '{1}' ToolsVersion installed",
                                                            runtime.Id, toolsVersion)
                                                        );
                }

                //one builder per solution
                string            builderKey = runtime.Id + " # " + solutionFile;
                RemoteBuildEngine builder;
                if (builders.TryGetValue(builderKey, out builder))
                {
                    builder.ReferenceCount++;
                    return(new RemoteProjectBuilder(file, builder));
                }

                //always start the remote process explicitly, even if it's using the current runtime and fx
                //else it won't pick up the assembly redirects from the builder exe
                var exe = GetExeLocation(runtime, toolsVersion);

                MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel();
                var pinfo = new ProcessStartInfo(exe)
                {
                    UseShellExecute       = false,
                    CreateNoWindow        = true,
                    RedirectStandardError = true,
                    RedirectStandardInput = true,
                };
                runtime.GetToolsExecutionEnvironment().MergeTo(pinfo);

                Process p = null;

                try {
                    IBuildEngine engine;
                    if (!runLocal)
                    {
                        p = runtime.ExecuteAssembly(pinfo);

                        // The builder app will write the build engine reference
                        // after reading the process id from the standard input
                        ManualResetEvent ev          = new ManualResetEvent(false);
                        string           responseKey = "[MonoDevelop]";
                        string           sref        = null;
                        p.ErrorDataReceived += (sender, e) => {
                            if (e.Data == null)
                            {
                                return;
                            }

                            if (e.Data.StartsWith(responseKey, StringComparison.Ordinal))
                            {
                                sref = e.Data.Substring(responseKey.Length);
                                ev.Set();
                            }
                            else
                            {
                                Console.WriteLine(e.Data);
                            }
                        };
                        p.BeginErrorReadLine();
                        p.StandardInput.WriteLine(Process.GetCurrentProcess().Id.ToString());
                        if (!ev.WaitOne(TimeSpan.FromSeconds(5)))
                        {
                            throw new Exception("MSBuild process could not be started");
                        }

                        byte[]          data = Convert.FromBase64String(sref);
                        MemoryStream    ms   = new MemoryStream(data);
                        BinaryFormatter bf   = new BinaryFormatter();
                        engine = (IBuildEngine)bf.Deserialize(ms);
                    }
                    else
                    {
                        var asm = System.Reflection.Assembly.LoadFrom(exe);
                        var t   = asm.GetType("MonoDevelop.Projects.Formats.MSBuild.BuildEngine");
                        engine = (IBuildEngine)Activator.CreateInstance(t);
                    }
                    engine.SetCulture(GettextCatalog.UICulture);
                    engine.SetGlobalProperties(GetCoreGlobalProperties(solutionFile));
                    foreach (var gpp in globalPropertyProviders)
                    {
                        engine.SetGlobalProperties(gpp.GetGlobalProperties());
                    }
                    builder = new RemoteBuildEngine(p, engine);
                } catch {
                    if (p != null)
                    {
                        try {
                            p.Kill();
                        } catch {
                        }
                    }
                    throw;
                }

                builders [builderKey]  = builder;
                builder.ReferenceCount = 1;
                builder.Disconnected  += delegate {
                    lock (builders)
                        builders.Remove(builderKey);
                };
                return(new RemoteProjectBuilder(file, builder));
            }
        }