예제 #1
0
        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));
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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());
        }
예제 #4
0
        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);
        }
예제 #5
0
        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());
        }
예제 #8
0
        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);
        }
예제 #9
0
 AddSetting(
     string name,
     Bam.Core.TokenizedStringArray value,
     string condition     = null,
     bool inheritExisting = false,
     bool arePaths        = false)
 {
     this.AddSetting(
         name,
         value.ToEnumerableWithoutDuplicates(),
         condition,
         inheritExisting,
         arePaths
         );
 }
예제 #10
0
        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");
 }
예제 #12
0
        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);
        }
예제 #13
0
 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);
            }
        }
예제 #16
0
        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);
        }