/// <summary> /// Builds the specified solution configuration. /// </summary> /// <param name="solutionConfiguration">The solution configuration.</param> /// <returns></returns> protected override BuildResult Build(Configuration solutionConfiguration) { bool bSuccess = true; bool outputUpdated; string tempFile = null; GacCache.RecreateDomain(); try { // obtain project configuration (corresponding with solution configuration) ConfigurationSettings cs = (ConfigurationSettings) BuildConfigurations[solutionConfiguration]; // perform prebuild actions (for VS.NET 2003 and higher) if (!PreBuild(cs)) { // no longer bother trying to build the project and do not // execute any post-build events return BuildResult.Failed; } // unregister types exposed to COM, and unregister type // library (if it exists) UnregisterForComInterop(cs, solutionConfiguration); // ensure temp directory exists if (!Directory.Exists(TemporaryFiles.BasePath)) { Directory.CreateDirectory(TemporaryFiles.BasePath); } // compile neutral and localized resx files CompileResXFiles(solutionConfiguration); // check if project output needs to be rebuilt if (CheckUpToDate(solutionConfiguration)) { Log(Level.Verbose, "Project is up-to-date."); // project output is up-to-date outputUpdated = false; } else { // prepare the project for build Prepare(solutionConfiguration); // check if project does not contain any sources if (_sourceFiles.Count == 0) { // create temp file tempFile = Path.GetTempFileName(); // add temp file to collection of sources to compile // as command line compilers require a least one source // file to be specified, but VS.NET supports empty // projects _sourceFiles[tempFile] = null; } string tempResponseFile = FileUtils.CombinePaths(TemporaryFiles.BasePath, CommandFile); using (StreamWriter sw = File.CreateText(tempResponseFile)) { // write compiler options WriteCompilerOptions(sw, solutionConfiguration); } Log(Level.Verbose, "Starting compiler..."); if (SolutionTask.Verbose) { using (StreamReader sr = new StreamReader(tempResponseFile)) { Log(Level.Verbose, "Commands:"); // increment indentation level SolutionTask.Project.Indent(); try { while (true) { // read line string line = sr.ReadLine(); if (line == null) { break; } // display line Log(Level.Verbose, " " + line); } } finally { // restore indentation level SolutionTask.Project.Unindent(); } } } ProcessStartInfo psi = GetProcessStartInfo(cs, tempResponseFile); psi.UseShellExecute = false; psi.RedirectStandardOutput = true; // start compiler Process p = Process.Start(psi); while (true) { // read line string line = p.StandardOutput.ReadLine(); if (line == null) { break; } // display line Log(Level.Info, line); } p.WaitForExit(); int exitCode = p.ExitCode; Log(Level.Verbose, "{0}! (exit code = {1})", (exitCode == 0) ? "Success" : "Failure", exitCode); if (exitCode > 0) { bSuccess = false; } // project output has been updated outputUpdated = true; } #region Process culture-specific resource files Log(Level.Verbose, "Building satellite assemblies..."); Hashtable resourceSets = GetLocalizedResources(); foreach (LocalizedResourceSet localizedResourceSet in resourceSets.Values) { AssemblyLinkerTask al = new AssemblyLinkerTask(); al.Project = SolutionTask.Project; al.NamespaceManager = SolutionTask.NamespaceManager; al.Parent = SolutionTask; al.BaseDirectory = cs.OutputDir; al.InitializeTaskConfiguration(); DirectoryInfo satelliteBuildDir = localizedResourceSet. GetBuildDirectory(cs); // ensure satellite build directory exists if (!satelliteBuildDir.Exists) { satelliteBuildDir.Create(); } al.OutputFile = localizedResourceSet.GetSatelliteAssemblyPath( cs, ProjectSettings); al.OutputTarget = "lib"; al.Culture = localizedResourceSet.Culture.Name; al.TemplateFile = new FileInfo(cs.BuildPath); foreach (Resource resource in localizedResourceSet.Resources) { FileInfo compiledResourceFile = null; if (resource.IsResX) { // localized resx files have already been compiled compiledResourceFile = resource.GetCompiledResourceFile( solutionConfiguration); } else { // compile resource compiledResourceFile = resource.Compile(solutionConfiguration); } // add resources to embed EmbeddedResource embeddedResource = new EmbeddedResource( compiledResourceFile.FullName, resource.GetManifestResourceName(solutionConfiguration)); al.EmbeddedResources.Add(embeddedResource); } // increment indentation level SolutionTask.Project.Indent(); try { Log(Level.Verbose, " - {0}", al.Culture); // run assembly linker al.Execute(); } finally { // restore indentation level SolutionTask.Project.Unindent(); } } #endregion Process culture-specific resource files #region Register project output for COM Interop // check if we need to build type library if (cs.RegisterForComInterop) { // create type library in output dir, and register it using // that path to match VS.NET string typeLibPath = GetTypeLibraryPath(cs); RegisterForComInterop(cs, solutionConfiguration, typeLibPath); // copy generated type library to object directory to match // VS.NET string objTypeLibPath = Path.ChangeExtension(cs.BuildPath, ".tlb"); CopyFile(new FileInfo(typeLibPath), new FileInfo (objTypeLibPath), SolutionTask); } #endregion Register project output for COM Interop #region Deploy project and configuration level output files // copy primary project output (and related files) Hashtable outputFiles = CollectionsUtil.CreateCaseInsensitiveHashtable(); GetOutputFiles(solutionConfiguration, outputFiles); foreach (DictionaryEntry de in outputFiles) { string srcPath = (string) de.Key; string relativePath = (string) de.Value; if (IsWebProject) { WebDavClient wdc = new WebDavClient(new Uri(_webProjectBaseUrl)); wdc.UploadFile(srcPath, FileUtils.CombinePaths(cs.RelativeOutputDir, relativePath).Replace(@"\", "/")); } else { // determine destination file FileInfo destFile = new FileInfo(FileUtils.CombinePaths(cs.OutputDir.FullName, relativePath)); // copy file using <copy> task CopyFile(new FileInfo(srcPath), destFile, SolutionTask); } } #endregion Deploy project and configuration level output files if (ProjectSettings.RunPostBuildEvent != null) { if (!PostBuild(cs, !outputUpdated || bSuccess, outputUpdated)) { bSuccess = false; } } if (!bSuccess) { Log(Level.Error, "Build failed."); return BuildResult.Failed; } return outputUpdated ? BuildResult.SuccessOutputUpdated : BuildResult.Success; } finally { // check if temporary file was created to support empty projects if (tempFile != null) { // ensure temp file is deleted File.Delete(tempFile); } } }
/// <summary> /// Link a list of files into a resource assembly. /// </summary> /// <param name="resourceFiles">The collection of resources.</param> /// <param name="resourceAssemblyFile">Resource assembly to generate</param> /// <param name="culture">Culture of the generated assembly.</param> protected void LinkResourceAssembly(Hashtable resourceFiles, FileInfo resourceAssemblyFile, string culture) { // defer to the assembly linker task AssemblyLinkerTask alink = new AssemblyLinkerTask(); // inherit project from current task alink.Project = Project; // inherit namespace manager from current task alink.NamespaceManager = NamespaceManager; // current task is parent alink.Parent = this; // make sure framework specific information is set alink.InitializeTaskConfiguration(); // set task properties alink.OutputFile = resourceAssemblyFile; alink.Culture = culture; alink.OutputTarget = "lib"; alink.TemplateFile = OutputFile; alink.KeyFile = KeyFile; alink.KeyContainer = KeyContainer; alink.DelaySign = DelaySign; // add resource files using the Arguments collection. foreach (string manifestname in resourceFiles.Keys) { string resourcefile = (string) resourceFiles[manifestname]; // add resources to embed EmbeddedResource embeddedResource = new EmbeddedResource( resourcefile, manifestname); alink.EmbeddedResources.Add(embeddedResource); } // increment indentation level Project.Indent(); try { // execute the nested task alink.Execute(); } finally { // restore indentation level Project.Unindent(); } }