public void Contains() { Assert.IsTrue(_array.Contains(new CloneableType("two"))); Assert.IsFalse(_array.Contains(new CloneableType("seven"))); }
CompilePackageAssembly( bool enforceBamAssemblyVersions = true, bool enableClean = true) { // validate build root if (null == Graph.Instance.BuildRoot) { throw new Exception("Build root has not been specified"); } var gatherSourceProfile = new TimeProfile(ETimingProfiles.GatherSource); gatherSourceProfile.StartProfile(); IdentifyAllPackages(enforceBamAssemblyVersions: enforceBamAssemblyVersions); var cleanFirst = CommandLineProcessor.Evaluate(new Options.CleanFirst()); if (enableClean && cleanFirst && System.IO.Directory.Exists(Graph.Instance.BuildRoot)) { Log.Info("Deleting build root '{0}'", Graph.Instance.BuildRoot); try { System.IO.Directory.Delete(Graph.Instance.BuildRoot, true); } catch (System.IO.IOException ex) { Log.Info("Failed to delete build root, because {0}. Continuing", ex.Message); } } if (!System.IO.Directory.Exists(Graph.Instance.BuildRoot)) { System.IO.Directory.CreateDirectory(Graph.Instance.BuildRoot); } BuildModeUtilities.ValidateBuildModePackage(); var definitions = new StringArray(); // gather source files var sourceCode = new StringArray(); int packageIndex = 0; foreach (var package in Graph.Instance.Packages) { Log.DebugMessage("{0}: '{1}' @ '{2}'", packageIndex, package.Version, (package.PackageRepositories.Count > 0) ? package.PackageRepositories[0] : "Not in a repository"); // to compile with debug information, you must compile the files // to compile without, we need to file contents to hash the source if (Graph.Instance.CompileWithDebugSymbols) { var scripts = package.GetScriptFiles(); sourceCode.AddRange(scripts); Log.DebugMessage(scripts.ToString("\n\t")); } else { foreach (var scriptFile in package.GetScriptFiles()) { using (var reader = new System.IO.StreamReader(scriptFile)) { sourceCode.Add(reader.ReadToEnd()); } Log.DebugMessage("\t'{0}'", scriptFile); } } foreach (var define in package.Definitions) { if (!definitions.Contains(define)) { definitions.Add(define); } } ++packageIndex; } // add/remove other definitions definitions.Add(VersionDefineForCompiler); definitions.Add(HostPlatformDefineForCompiler); definitions.Sort(); gatherSourceProfile.StopProfile(); var assemblyCompileProfile = new TimeProfile(ETimingProfiles.AssemblyCompilation); assemblyCompileProfile.StartProfile(); // assembly is written to the build root var cachedAssemblyPathname = System.IO.Path.Combine(Graph.Instance.BuildRoot, "CachedPackageAssembly"); cachedAssemblyPathname = System.IO.Path.Combine(cachedAssemblyPathname, Graph.Instance.MasterPackage.Name) + ".dll"; var hashPathName = System.IO.Path.ChangeExtension(cachedAssemblyPathname, "hash"); string thisHashCode = null; var cacheAssembly = !CommandLineProcessor.Evaluate(new Options.DisableCacheAssembly()); string compileReason = null; if (Graph.Instance.CompileWithDebugSymbols) { compileReason = "debug symbols were enabled"; } else { // can an existing assembly be reused? thisHashCode = GetPackageHash(sourceCode, definitions, Graph.Instance.MasterPackage.BamAssemblies); if (cacheAssembly) { if (System.IO.File.Exists(hashPathName)) { using (var reader = new System.IO.StreamReader(hashPathName)) { var diskHashCode = reader.ReadLine(); if (diskHashCode.Equals(thisHashCode)) { Log.DebugMessage("Cached assembly used '{0}', with hash {1}", cachedAssemblyPathname, diskHashCode); Log.Detail("Re-using existing package assembly"); Graph.Instance.ScriptAssemblyPathname = cachedAssemblyPathname; assemblyCompileProfile.StopProfile(); return true; } else { compileReason = "package source has changed since the last compile"; } } } else { compileReason = "no previously compiled package assembly exists"; } } else { compileReason = "user has disabled package assembly caching"; } } // use the compiler in the current runtime version to build the assembly of packages var clrVersion = System.Environment.Version; var compilerVersion = System.String.Format("v{0}.{1}", clrVersion.Major, clrVersion.Minor); Log.Detail("Compiling package assembly (C# compiler {0}{1}), because {2}.", compilerVersion, Graph.Instance.ProcessState.TargetFrameworkVersion != null ? (", targetting " + Graph.Instance.ProcessState.TargetFrameworkVersion) : string.Empty, compileReason); var providerOptions = new System.Collections.Generic.Dictionary<string, string>(); providerOptions.Add("CompilerVersion", compilerVersion); if (Graph.Instance.ProcessState.RunningMono) { Log.DebugMessage("Compiling assembly for Mono"); } using (var provider = new Microsoft.CSharp.CSharpCodeProvider(providerOptions)) { var compilerParameters = new System.CodeDom.Compiler.CompilerParameters(); compilerParameters.TreatWarningsAsErrors = true; compilerParameters.WarningLevel = 4; compilerParameters.GenerateExecutable = false; compilerParameters.GenerateInMemory = false; if (Graph.Instance.CompileWithDebugSymbols) { compilerParameters.OutputAssembly = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Graph.Instance.MasterPackage.Name) + ".dll"; } else { compilerParameters.OutputAssembly = cachedAssemblyPathname; } var compilerOptions = "/checked+ /unsafe-"; if (Graph.Instance.CompileWithDebugSymbols) { compilerParameters.IncludeDebugInformation = true; compilerOptions += " /optimize-"; } else { compilerOptions += " /optimize+"; } compilerOptions += " /platform:anycpu"; // define strings compilerOptions += " /define:" + definitions.ToString(';'); compilerParameters.CompilerOptions = compilerOptions; if (provider.Supports(System.CodeDom.Compiler.GeneratorSupport.Resources)) { // Bam assembly // TODO: Q: why is it only for the master package? Why not all of them, which may have additional dependencies? foreach (var assembly in Graph.Instance.MasterPackage.BamAssemblies) { var assemblyFileName = System.String.Format("{0}.dll", assembly.Name); var assemblyPathName = System.IO.Path.Combine(Graph.Instance.ProcessState.ExecutableDirectory, assemblyFileName); compilerParameters.ReferencedAssemblies.Add(assemblyPathName); } // DotNet assembly foreach (var desc in Graph.Instance.MasterPackage.DotNetAssemblies) { var assemblyFileName = System.String.Format("{0}.dll", desc.Name); compilerParameters.ReferencedAssemblies.Add(assemblyFileName); } if (Graph.Instance.ProcessState.RunningMono) { compilerParameters.ReferencedAssemblies.Add("Mono.Posix.dll"); } } else { throw new Exception("C# compiler does not support Resources"); } System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(compilerParameters.OutputAssembly)); var results = Graph.Instance.CompileWithDebugSymbols ? provider.CompileAssemblyFromFile(compilerParameters, sourceCode.ToArray()) : provider.CompileAssemblyFromSource(compilerParameters, sourceCode.ToArray()); if (results.Errors.HasErrors || results.Errors.HasWarnings) { Log.ErrorMessage("Failed to compile package '{0}'. There are {1} errors.", Graph.Instance.MasterPackage.FullName, results.Errors.Count); foreach (System.CodeDom.Compiler.CompilerError error in results.Errors) { Log.ErrorMessage("\t{0}({1}): {2} {3}", error.FileName, error.Line, error.ErrorNumber, error.ErrorText); } return false; } if (!Graph.Instance.CompileWithDebugSymbols) { if (cacheAssembly) { using (var writer = new System.IO.StreamWriter(hashPathName)) { writer.WriteLine(thisHashCode); } } else { // will not throw if the file doesn't exist System.IO.File.Delete(hashPathName); } } Log.DebugMessage("Written assembly to '{0}'", compilerParameters.OutputAssembly); Graph.Instance.ScriptAssemblyPathname = compilerParameters.OutputAssembly; } assemblyCompileProfile.StopProfile(); return true; }