AddSetting( string name, Bam.Core.TokenizedStringArray value, string condition = null, bool inheritExisting = false) { lock (this.Settings) { if (0 == value.Count) { return; } var linearized = value.ToString(';'); if (this.Settings.Any(item => item.Name == name && item.Condition == condition)) { var settingOption = this.Settings.Where(item => item.Name == name && item.Condition == condition).First(); if (settingOption.Value.Contains(linearized)) { return; } throw new Bam.Core.Exception("Cannot append {3}, to the option {0} as it already exists for condition {1}: {2}", name, condition, settingOption.Value.ToString(), linearized); } this.Settings.AddUnique(new VSSetting(name, inheritExisting ? System.String.Format("{0};%({1})", linearized, name) : linearized, condition)); } }
VisualCCommon.IRuntimeLibraryPathMeta.CRuntimePaths( C.EBit depth) { // only redist the VisualC specific version runtime, and the universal CRT // don't redist the api-ms-win-crt-*-l1-1-0.dll files from the WindowsSDK, as I can find no reference // to needing to do so var windowsSDKMeta = Bam.Core.Graph.Instance.PackageMetaData <WindowsSDK.MetaData>("WindowsSDK"); var dynamicLibPaths = new Bam.Core.TokenizedStringArray(); switch (depth) { case C.EBit.ThirtyTwo: { dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/VC/redist/x86/Microsoft.VC140.CRT/vcruntime140.dll", null, new Bam.Core.TokenizedStringArray(this.InstallDir))); dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/Redist/ucrt/DLLs/x86/ucrtbase.dll", null, new Bam.Core.TokenizedStringArray(windowsSDKMeta.InstallDirSDK10))); } break; case C.EBit.SixtyFour: { dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/VC/redist/x64/Microsoft.VC140.CRT/vcruntime140.dll", null, new Bam.Core.TokenizedStringArray(this.InstallDir))); dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/Redist/ucrt/DLLs/x64/ucrtbase.dll", null, new Bam.Core.TokenizedStringArray(windowsSDKMeta.InstallDirSDK10))); } break; default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } return(dynamicLibPaths); }
toRelativePaths( Bam.Core.TokenizedStringArray paths) { var programFiles = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles); var programFilesX86 = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86); var contatenated = new System.Text.StringBuilder(); foreach (var path in paths) { var pathString = path.Parse(); if (pathString.StartsWith(programFiles) || pathString.StartsWith(programFilesX86)) { contatenated.AppendFormat("{0};", pathString); continue; } var relative = Bam.Core.RelativePathUtilities.GetPath(pathString, this.Project.ProjectPath); if (!Bam.Core.RelativePathUtilities.IsPathAbsolute(relative)) { contatenated.Append("$(ProjectDir)"); } contatenated.AppendFormat("{0};", relative); } return(contatenated.ToString()); }
VisualCCommon.IRuntimeLibraryPathMeta.CxxRuntimePaths( C.EBit depth) { var redistdir = new Bam.Core.TokenizedStringArray(this.Environment(depth)["VCToolsRedistDir"]); var dynamicLibPaths = new Bam.Core.TokenizedStringArray(); switch (depth) { case C.EBit.ThirtyTwo: dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/x86/Microsoft.VC141.CRT/msvcp140.dll", null, redistdir ) ); break; case C.EBit.SixtyFour: dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/x64/Microsoft.VC141.CRT/msvcp140.dll", null, redistdir ) ); break; default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } return(dynamicLibPaths); }
IExternalSourceGeneratorPolicy.GenerateSource( ExternalSourceGenerator sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executable, Bam.Core.TokenizedStringArray arguments, Bam.Core.TokenizedString output_directory, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> expected_output_files, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> input_files ) { Bam.Core.IOWrapper.CreateDirectoryIfNotExists(output_directory.ToString()); var program = executable.ToStringQuoteIfNecessary(); var linearised_args = arguments.ToString(' '); Bam.Core.Log.Info("Running: {0} {1}", program, linearised_args); Bam.Core.OSUtilities.RunExecutable(program, linearised_args); foreach (var expected_file in expected_output_files) { if (!System.IO.File.Exists(expected_file.Value.ToString())) { throw new Bam.Core.Exception( "Expected '{0}' to exist (key={1}), but it does not", expected_file.Value.ToString(), expected_file.Key ); } } }
IExternalSourceGeneratorPolicy.GenerateSource( ExternalSourceGenerator sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executable, Bam.Core.TokenizedStringArray arguments, Bam.Core.TokenizedString output_directory, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> expected_output_files, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> input_files ) { var encapsulating = sender.GetEncapsulatingReferencedModule(); var solution = Bam.Core.Graph.Instance.MetaData as VSSolutionBuilder.VSSolution; var project = solution.EnsureProjectExists(encapsulating); var config = project.GetConfiguration(encapsulating); var args = new Bam.Core.StringArray(); args.Add(System.String.Format("{0} {1}", executable.ToStringQuoteIfNecessary(), arguments.ToString(' '))); foreach (var input in input_files.Values) { config.AddOtherFile(input); var customBuild = config.GetSettingsGroup( VSSolutionBuilder.VSSettingsGroup.ESettingsGroup.CustomBuild, include: input, uniqueToProject: true ); customBuild.AddSetting("Command", args.ToString(' '), condition: config.ConditionText); customBuild.AddSetting("Message", System.String.Format("Generating outputs from {0}", input.ToString()), condition: config.ConditionText); customBuild.AddSetting("Outputs", expected_output_files.Values, condition: config.ConditionText); customBuild.AddSetting("AdditionalInputs", input_files.Values, condition: config.ConditionText); } }
IExternalSourceGeneratorPolicy.GenerateSource( ExternalSourceGenerator sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executable, Bam.Core.TokenizedStringArray arguments, Bam.Core.TokenizedString output_directory, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> expected_output_files, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> input_files ) { var meta = new MakeFileBuilder.MakeFileMeta(sender); var rule = meta.AddRule(); rule.AddTarget(expected_output_files.Values.First()); foreach (var input in input_files.Values) { rule.AddPrerequisite(input); } rule.AddShellCommand( System.String.Format("{0} {1}", executable.ToStringQuoteIfNecessary(), arguments.ToString(' ')) ); meta.CommonMetaData.AddDirectory(output_directory.ToString()); }
VisualCCommon.IRuntimeLibraryPathMeta.CRuntimePaths( C.EBit depth) { // only redist the VisualC specific version runtime, and the universal CRT // vcvarsall.bat defines UniversalCRTSdkDir which is suitable for use with both WinSDK8.1 and 10.x // don't redist the api-ms-win-crt-*-l1-1-0.dll files from the WindowsSDK, as I can find no reference // to needing to do so var env = this.Environment(depth); var redistdir = new Bam.Core.TokenizedStringArray(env["VCToolsRedistDir"]); var winsdkdir = env["UniversalCRTSdkDir"]; var dynamicLibPaths = new Bam.Core.TokenizedStringArray(); switch (depth) { case C.EBit.ThirtyTwo: { dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/x86/Microsoft.VC141.CRT/vcruntime140.dll", null, redistdir ) ); dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/Redist/ucrt/DLLs/x86/ucrtbase.dll", null, new Bam.Core.TokenizedStringArray(winsdkdir) ) ); } break; case C.EBit.SixtyFour: { dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/x64/Microsoft.VC141.CRT/vcruntime140.dll", null, redistdir ) ); dynamicLibPaths.Add( Bam.Core.TokenizedString.Create( "$(0)/Redist/ucrt/DLLs/x64/ucrtbase.dll", null, new Bam.Core.TokenizedStringArray(winsdkdir) ) ); } break; default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } return(dynamicLibPaths); }
AddSetting( string name, Bam.Core.TokenizedStringArray value, string condition = null, bool inheritExisting = false, bool arePaths = false) { this.AddSetting( name, value.ToEnumerableWithoutDuplicates(), condition, inheritExisting, arePaths ); }
VisualCCommon.IRuntimeLibraryPathMeta.CxxRuntimePaths( C.EBit depth) { var dynamicLibPaths = new Bam.Core.TokenizedStringArray(); switch (depth) { case C.EBit.ThirtyTwo: dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/VC/redist/x86/Microsoft.VC110.CRT/msvcp110.dll", null, new Bam.Core.TokenizedStringArray(this.InstallDir))); break; case C.EBit.SixtyFour: dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("$(0)/VC/redist/x64/Microsoft.VC110.CRT/msvcp110.dll", null, new Bam.Core.TokenizedStringArray(this.InstallDir))); break; default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } return(dynamicLibPaths); }
configure( string architecture) { if (this.EnvironmentVariables.ContainsKey("WindowsSdkDir")) { var tokenised_strings = new Bam.Core.TokenizedStringArray(); tokenised_strings.AddRangeUnique(this.EnvironmentVariables["WindowsSdkDir"]); this.Macros.Add( "CompilerPath", Bam.Core.TokenizedString.Create( System.String.Format("$(0)/bin/{0}/rc.exe", architecture), null, tokenised_strings ) ); } else { throw new Bam.Core.Exception("Unable to determine resource compiler path, as %WindowsSdkDir% was not defined"); } this.Macros.AddVerbatim("objext", ".res"); }
VisualCCommon.IRuntimeLibraryPathMeta.CxxRuntimePaths( C.EBit depth) { // https://social.msdn.microsoft.com/Forums/en-US/7b703997-e0d2-4b25-bb3a-c6a00141221d/visual-studio-2010-missing-mscvr100dll?forum=Vsexpressvcs var dynamicLibPaths = new Bam.Core.TokenizedStringArray(); if (Bam.Core.OSUtilities.Is64BitHosting) { switch (depth) { case C.EBit.ThirtyTwo: dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("C:/Windows/SysWOW64/msvcp100.dll", null)); break; case C.EBit.SixtyFour: dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("C:/Windows/System32/msvcp100.dll", null)); break; default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } } else { switch (depth) { case C.EBit.ThirtyTwo: dynamicLibPaths.Add(Bam.Core.TokenizedString.Create("C:/Windows/System32/msvcp100.dll", null)); break; case C.EBit.SixtyFour: throw new Bam.Core.Exception("64-bit CRT is not available on 32-bit operating systems."); default: throw new Bam.Core.Exception("Unrecognized bit depth, {0}", depth); } } return(dynamicLibPaths); }
toRelativePaths( Bam.Core.TokenizedStringArray paths) { return(toRelativePaths(paths.ToEnumerableWithoutDuplicates())); }
IExternalSourceGeneratorPolicy.GenerateSource( ExternalSourceGenerator sender, Bam.Core.ExecutionContext context, Bam.Core.TokenizedString executable, Bam.Core.TokenizedStringArray arguments, Bam.Core.TokenizedString output_directory, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> expected_output_files, System.Collections.Generic.IReadOnlyDictionary <string, Bam.Core.TokenizedString> input_files ) { var encapsulating = sender.GetEncapsulatingReferencedModule(); var workspace = Bam.Core.Graph.Instance.MetaData as XcodeBuilder.WorkspaceMeta; var target = workspace.EnsureTargetExists(encapsulating); if (encapsulating == sender) { target.SetType(XcodeBuilder.Target.EProductType.Utility); } var configuration = target.GetConfiguration(encapsulating); if (encapsulating == sender) { configuration.SetProductName(Bam.Core.TokenizedString.CreateVerbatim("${TARGET_NAME}")); } var commands = new Bam.Core.StringArray(); commands.Add( System.String.Format( "[[ ! -d {0} ]] && mkdir -p {0}", Bam.Core.IOWrapper.EscapeSpacesInPath(output_directory.ToString()) ) ); var condition_text = new System.Text.StringBuilder(); condition_text.Append("if [[ "); var last_output = expected_output_files.Values.Last(); foreach (var output in expected_output_files.Values) { var output_path = Bam.Core.IOWrapper.EscapeSpacesInPath(output.ToString()); condition_text.AppendFormat("! -e {0} ", output_path); foreach (var input in input_files.Values) { var input_path = Bam.Core.IOWrapper.EscapeSpacesInPath(input.ToString()); condition_text.AppendFormat("|| {1} -nt {0} ", output_path, input_path); } if (output != last_output) { condition_text.AppendFormat("|| "); } } condition_text.AppendLine("]]"); condition_text.AppendLine("then"); var cmd_line = System.String.Format("{0} {1}", executable.ToStringQuoteIfNecessary(), arguments.ToString(' ')); condition_text.AppendLine(System.String.Format("\techo {0}", cmd_line)); condition_text.AppendLine(System.String.Format("\t{0}", cmd_line)); condition_text.AppendLine("fi"); commands.Add(condition_text.ToString()); target.AddPreBuildCommands(commands, configuration); }
Convert( this C.ICommonCompilerSettings settings, Bam.Core.Module module, VSSolutionBuilder.VSSettingsGroup vsSettingsGroup, string condition) { // write nothing for disabled debug symbols, otherwise the source files rebuild continually // and reports a warning that the pdb file does not exist // the IDE can write None into the .vcxproj, but this has the same behaviour // https://connect.microsoft.com/VisualStudio/feedback/details/833494/project-with-debug-information-disabled-always-rebuilds if (settings.DebugSymbols.HasValue) { if (settings.DebugSymbols.Value) { vsSettingsGroup.AddSetting("DebugInformationFormat", "OldStyle", condition); } } if (settings.DisableWarnings.Count > 0) { vsSettingsGroup.AddSetting("DisableSpecificWarnings", settings.DisableWarnings, condition, inheritExisting: true); } if (settings.IncludePaths.Count > 0 || settings.SystemIncludePaths.Count > 0) { var combined = new Bam.Core.TokenizedStringArray(settings.IncludePaths.Union(settings.SystemIncludePaths)); vsSettingsGroup.AddSetting("AdditionalIncludeDirectories", combined, condition, inheritExisting: true, arePaths: true); } if (settings.Optimization.HasValue && settings.Optimization.Value != C.EOptimization.Custom) { System.Func <string> optimization = () => { switch (settings.Optimization.Value) { case C.EOptimization.Off: return("Disabled"); case C.EOptimization.Size: return("MinSpace"); case C.EOptimization.Speed: return("MaxSpeed"); case C.EOptimization.Custom: throw new Bam.Core.Exception("Should never get here"); default: throw new Bam.Core.Exception("Unknown optimization type, {0}", settings.Optimization.Value.ToString()); } }; vsSettingsGroup.AddSetting("Optimization", optimization(), condition); } if (settings.OmitFramePointer.HasValue) { vsSettingsGroup.AddSetting("OmitFramePointers", settings.OmitFramePointer.Value, condition); } if (settings.PreprocessorDefines.Count > 0) { vsSettingsGroup.AddSetting("PreprocessorDefinitions", settings.PreprocessorDefines, condition, inheritExisting: true); } if (settings.PreprocessorUndefines.Count > 0) { vsSettingsGroup.AddSetting("UndefinePreprocessorDefinitions", settings.PreprocessorUndefines, condition, inheritExisting: true); } if (settings.TargetLanguage.HasValue) { System.Func <string> targetLanguage = () => { switch (settings.TargetLanguage.Value) { case C.ETargetLanguage.C: return("CompileAsC"); case C.ETargetLanguage.Cxx: return("CompileAsCpp"); case C.ETargetLanguage.Default: return("Default"); default: throw new Bam.Core.Exception("Unknown target language, {0}", settings.TargetLanguage.Value.ToString()); } }; vsSettingsGroup.AddSetting("CompileAs", targetLanguage(), condition); } if (settings.WarningsAsErrors.HasValue) { vsSettingsGroup.AddSetting("TreatWarningAsError", settings.WarningsAsErrors.Value, condition); } if (settings.OutputType.HasValue) { vsSettingsGroup.AddSetting("PreprocessToFile", settings.OutputType.Value == C.ECompilerOutput.Preprocess, condition); if (module is C.ObjectFile) // rather than ObjectFileCollection { vsSettingsGroup.AddSetting("ObjectFileName", module.GeneratedPaths[C.ObjectFile.Key], condition); } } if (settings.NamedHeaders.Count > 0) { vsSettingsGroup.AddSetting("ForcedIncludeFiles", settings.NamedHeaders, condition, inheritExisting: true); } }
execute_vcvars( C.EBit depth, bool has64bithost_32bitcross, bool hasNative64BitTools, Bam.Core.StringArray inherited_envvars, System.Collections.Generic.Dictionary <string, Bam.Core.StringArray> required_envvars ) { var startinfo = new System.Diagnostics.ProcessStartInfo(); startinfo.FileName = @"c:\Windows\System32\cmd.exe"; startinfo.EnvironmentVariables.Clear(); if (null != inherited_envvars) { foreach (var inherited in inherited_envvars) { startinfo.EnvironmentVariables.Add(inherited, System.Environment.GetEnvironmentVariable(inherited)); } } if (null != required_envvars) { foreach (System.Collections.Generic.KeyValuePair <string, Bam.Core.StringArray> required in required_envvars) { if (startinfo.EnvironmentVariables.ContainsKey(required.Key)) { var existing_value = startinfo.EnvironmentVariables[required.Key]; var updated_value = System.String.Format( "{0};{1}", System.Environment.ExpandEnvironmentVariables(required.Value.ToString(';')), existing_value ); startinfo.EnvironmentVariables[required.Key] = updated_value; } else { startinfo.EnvironmentVariables.Add(required.Key, System.Environment.ExpandEnvironmentVariables(required.Value.ToString(';'))); } } } startinfo.UseShellExecute = false; startinfo.RedirectStandardInput = true; startinfo.RedirectStandardOutput = true; startinfo.RedirectStandardError = true; System.Func <string> vcvarsall_command = () => { var command_and_args = new System.Text.StringBuilder(); command_and_args.Append("vcvarsall.bat "); switch (depth) { case C.EBit.ThirtyTwo: { if (Bam.Core.OSUtilities.Is64BitHosting && has64bithost_32bitcross) { command_and_args.Append("amd64_x86 "); } else { command_and_args.Append("x86 "); } } break; case C.EBit.SixtyFour: { if (Bam.Core.OSUtilities.Is64BitHosting && hasNative64BitTools) { command_and_args.Append("amd64 "); } else { command_and_args.Append("x86_amd64 "); } } break; } // VisualC packages define their 'default' WindowsSDK package to function with // if this is different to what is being used, append the version fo the vcvarsall.bat command var visualC = Bam.Core.Graph.Instance.Packages.First(item => item.Name == "VisualC"); var defaultWindowsSDKVersion = visualC.Dependents.First(item => item.Item1 == "WindowsSDK").Item2; var windowsSDK = Bam.Core.Graph.Instance.Packages.FirstOrDefault(item => item.Name == "WindowsSDK"); if (null != windowsSDK) { if (windowsSDK.Version != defaultWindowsSDKVersion) { command_and_args.Append(System.String.Format("{0} ", windowsSDK.Version)); } else { var option_type = System.Type.GetType("WindowsSDK.Options.WindowsSDK10Version", throwOnError: false); if (null != option_type) { var option_type_instance = System.Activator.CreateInstance(option_type) as Bam.Core.IStringCommandLineArgument; if (null != option_type_instance) { var win10Option = Bam.Core.CommandLineProcessor.Evaluate(option_type_instance); if (null != win10Option) { command_and_args.Append(System.String.Format("{0} ", win10Option)); } } } } } return(command_and_args.ToString()); }; var environment_generator_cmdline = System.String.Empty; // allow the WindowsSDK to provide an alternative mechanism for generating // and environment in which to execute VisualC and WindowsSDK tools var windowssdk_meta = Bam.Core.Graph.Instance.PackageMetaData <WindowsSDK.MetaData>("WindowsSDK"); if (windowssdk_meta.Contains("setenvdir") && windowssdk_meta.Contains("setenvcmd")) { startinfo.WorkingDirectory = windowssdk_meta["setenvdir"] as string; environment_generator_cmdline = windowssdk_meta["setenvcmd"] as string; switch (depth) { case C.EBit.ThirtyTwo: environment_generator_cmdline += " /x86"; break; case C.EBit.SixtyFour: environment_generator_cmdline += " /x64"; break; } } else { startinfo.WorkingDirectory = System.IO.Path.Combine(this.InstallDir.ToString(), subpath_to_vcvars); environment_generator_cmdline = vcvarsall_command(); } // allow the WindowsSDK to override the VisualStudio project's PlatformToolset if (windowssdk_meta.Contains("PlatformToolset")) { var vc_meta = Bam.Core.Graph.Instance.PackageMetaData <VisualC.MetaData>("VisualC"); vc_meta.PlatformToolset = windowssdk_meta["PlatformToolset"] as string; } var arguments = new System.Text.StringBuilder(); arguments.AppendFormat("/C {0} && SET", environment_generator_cmdline); startinfo.Arguments = arguments.ToString(); var process = new System.Diagnostics.Process(); process.StartInfo = startinfo; // if you don't async read the output, then the process will never finish // as the buffer is filled up // EOLs will also be trimmed from these, so always append whole lines var stdout = new System.Text.StringBuilder(); process.OutputDataReceived += (sender, args) => stdout.AppendLine(args.Data); var stderr = new System.Text.StringBuilder(); process.ErrorDataReceived += (sender, args) => stderr.AppendLine(args.Data); process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.StandardInput.Close(); process.WaitForExit(); if (process.ExitCode != 0) { throw new Bam.Core.Exception("{0} failed: {1}", environment_generator_cmdline, stderr.ToString()); } var env = new System.Collections.Generic.Dictionary <string, Bam.Core.TokenizedStringArray>(); var lines = stdout.ToString().Split( new[] { System.Environment.NewLine }, System.StringSplitOptions.RemoveEmptyEntries ); foreach (var line in lines) { Bam.Core.Log.DebugMessage("{0}->{1}", environment_generator_cmdline, line); var equals_index = line.IndexOf('='); if (-1 == equals_index) { continue; } var key = line.Remove(equals_index); var value = line.Remove(0, equals_index + 1); if (System.String.IsNullOrEmpty(key) || System.String.IsNullOrEmpty(value)) { continue; } var splitValue = value.Split(new[] { ';' }); var valueArray = new Bam.Core.TokenizedStringArray(); foreach (var v in splitValue) { valueArray.Add(Bam.Core.TokenizedString.CreateVerbatim(v)); } env.Add(key, valueArray); } Bam.Core.Log.Info(@"Generating {0}-bit build environment using '{1}\{2}'", (int)depth, startinfo.WorkingDirectory, environment_generator_cmdline.TrimEnd() ); foreach (System.Collections.Generic.KeyValuePair <string, Bam.Core.TokenizedStringArray> entry in env) { Bam.Core.Log.DebugMessage("\t{0} = {1}", entry.Key, entry.Value.ToString(';')); } return(env); }