IArchivingPolicy.Archive(
            StaticLibrary sender,
            Bam.Core.ExecutionContext context,
            Bam.Core.TokenizedString libraryPath,
            System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> objectFiles,
            System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> headers)
        {
            if (0 == objectFiles.Count)
            {
                return;
            }

            var workspace = Bam.Core.Graph.Instance.MetaData as XcodeBuilder.WorkspaceMeta;
            var target    = workspace.EnsureTargetExists(sender);

            target.EnsureOutputFileReferenceExists(
                sender.CreateTokenizedString("@filename($(0))", libraryPath),
                XcodeBuilder.FileReference.EFileType.Archive,
                XcodeBuilder.Target.EProductType.StaticLibrary);
            var configuration = target.GetConfiguration(sender);

            if (sender.Macros["OutputName"].Equals(sender.Macros["modulename"]))
            {
                configuration.SetProductName(Bam.Core.TokenizedString.CreateVerbatim("${TARGET_NAME}"));
            }
            else
            {
                configuration.SetProductName(sender.Macros["OutputName"]);
            }

            foreach (var header in headers)
            {
                target.EnsureHeaderFileExists((header as HeaderFile).InputPath);
            }

            var excludedSource  = new XcodeBuilder.MultiConfigurationValue();
            var realObjectFiles = objectFiles.Where(item => !(item is AssembledObjectFile)); // C,C++,ObjC,ObjC++

            if (realObjectFiles.Any())
            {
                var xcodeConvertParameterTypes = new Bam.Core.TypeArray
                {
                    typeof(Bam.Core.Module),
                    typeof(XcodeBuilder.Configuration)
                };

                var sharedSettings = C.SettingsBase.SharedSettings(
                    realObjectFiles,
                    typeof(ClangCommon.XcodeCompilerImplementation),
                    typeof(XcodeProjectProcessor.IConvertToProject),
                    xcodeConvertParameterTypes);
                (sharedSettings as XcodeProjectProcessor.IConvertToProject).Convert(sender, configuration);

                foreach (var objFile in realObjectFiles)
                {
                    if (!(objFile as C.ObjectFileBase).PerformCompilation)
                    {
                        var fullPath = (objFile as C.ObjectFileBase).InputPath.Parse();
                        var filename = System.IO.Path.GetFileName(fullPath);
                        excludedSource.Add(filename);
                    }

                    var buildFile     = objFile.MetaData as XcodeBuilder.BuildFile;
                    var deltaSettings = (objFile.Settings as C.SettingsBase).CreateDeltaSettings(sharedSettings, objFile);
                    if (null != deltaSettings)
                    {
                        var commandLine = new Bam.Core.StringArray();
                        (deltaSettings as CommandLineProcessor.IConvertToCommandLine).Convert(commandLine);
                        if (commandLine.Count > 0)
                        {
                            // Cannot set per-file-per-configuration settings, so blend them together
                            if (null == buildFile.Settings)
                            {
                                buildFile.Settings = commandLine;
                            }
                            else
                            {
                                buildFile.Settings.AddRangeUnique(commandLine);
                            }
                        }
                    }
                    configuration.BuildFiles.Add(buildFile);
                }

                // now deal with other object file types
                var assembledObjectFiles = objectFiles.Where(item => item is AssembledObjectFile);
                foreach (var asmObj in assembledObjectFiles)
                {
                    var buildFile = asmObj.MetaData as XcodeBuilder.BuildFile;
                    configuration.BuildFiles.Add(buildFile);
                }
            }
            else
            {
                (objectFiles[0].Settings as XcodeProjectProcessor.IConvertToProject).Convert(sender, configuration);
                foreach (var objFile in objectFiles)
                {
                    if (!(objFile as C.ObjectFileBase).PerformCompilation)
                    {
                        var fullPath = (objFile as C.ObjectFileBase).InputPath.Parse();
                        var filename = System.IO.Path.GetFileName(fullPath);
                        excludedSource.Add(filename);
                    }

                    var buildFile = objFile.MetaData as XcodeBuilder.BuildFile;
                    configuration.BuildFiles.Add(buildFile);
                }
            }

            configuration["EXCLUDED_SOURCE_FILE_NAMES"] = excludedSource;

            // convert librarian settings to the Xcode project
            if (sender.Settings is XcodeProjectProcessor.IConvertToProject)
            {
                (sender.Settings as XcodeProjectProcessor.IConvertToProject).Convert(sender, configuration);
            }

            // order only dependents
            foreach (var required in sender.Requirements)
            {
                if (null == required.MetaData)
                {
                    continue;
                }
                if (required is HeaderLibrary)
                {
                    // the target for a HeaderLibrary has no FileReference output, and thus cannot be an order only dependency
                    continue;
                }

                var requiredTarget = required.MetaData as XcodeBuilder.Target;
                if (null != requiredTarget)
                {
                    target.Requires(requiredTarget);
                }
            }
            // any non-C module targets should be order-only dependencies
            // note: this is unlikely to happen, as StaticLibraries don't have hard 'dependencies'
            // because there is no fixed 'link' action at the end
            foreach (var dependent in sender.Dependents)
            {
                if (null == dependent.MetaData)
                {
                    continue;
                }
                if (dependent is C.CModule)
                {
                    continue;
                }
                var dependentTarget = dependent.MetaData as XcodeBuilder.Target;
                if (null != dependentTarget)
                {
                    target.Requires(dependentTarget);
                }
            }
            // however, there may be forwarded libraries, and these are useful order only dependents
            foreach (var dependent in (sender as IForwardedLibraries).ForwardedLibraries)
            {
                if (null == dependent.MetaData)
                {
                    continue;
                }
                var dependentTarget = dependent.MetaData as XcodeBuilder.Target;
                if (null != dependentTarget)
                {
                    target.Requires(dependentTarget);
                }
            }
        }
        IArchivingPolicy.Archive(
            StaticLibrary sender,
            Bam.Core.ExecutionContext context,
            Bam.Core.TokenizedString libraryPath,
            System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> objectFiles,
            System.Collections.ObjectModel.ReadOnlyCollection <Bam.Core.Module> headers)
        {
            if (0 == objectFiles.Count)
            {
                return;
            }

            var solution = Bam.Core.Graph.Instance.MetaData as VSSolutionBuilder.VSSolution;
            var project  = solution.EnsureProjectExists(sender);
            var config   = project.GetConfiguration(sender);

            config.SetType(VSSolutionBuilder.VSProjectConfiguration.EType.StaticLibrary);
            config.SetOutputPath(libraryPath);
            config.EnableIntermediatePath();

            foreach (var header in headers)
            {
                config.AddHeaderFile(header as HeaderFile);
            }

            var compilerGroup = config.GetSettingsGroup(VSSolutionBuilder.VSSettingsGroup.ESettingsGroup.Compiler);

            var realObjectFiles = objectFiles.Where(item => !((item is WinResource) || (item is AssembledObjectFile)));

            if (realObjectFiles.Any())
            {
                var vsConvertParameterTypes = new Bam.Core.TypeArray
                {
                    typeof(Bam.Core.Module),
                    typeof(VSSolutionBuilder.VSSettingsGroup),
                    typeof(string)
                };

                var sharedSettings = C.SettingsBase.SharedSettings(
                    realObjectFiles,
                    typeof(VisualCCommon.VSSolutionImplementation),
                    typeof(VisualStudioProcessor.IConvertToProject),
                    vsConvertParameterTypes);
                (sharedSettings as VisualStudioProcessor.IConvertToProject).Convert(sender, compilerGroup);

                foreach (var objFile in realObjectFiles)
                {
                    var deltaSettings = (objFile.Settings as C.SettingsBase).CreateDeltaSettings(sharedSettings, objFile);
                    config.AddSourceFile(objFile, deltaSettings);
                }
            }

            // now handle the other object file types

            // TODO: if there were many resource files, this could also have a common settings group? Not sure if VS supports this
            // and it's not as likely to have many resource files, as it would have many source files
            var resourceObjectFiles = objectFiles.Where(item => item is WinResource);

            foreach (var resObj in resourceObjectFiles)
            {
                config.AddResourceFile(resObj as WinResource, resObj.Settings);
            }

            var assembledObjectFiles = objectFiles.Where(item => item is AssembledObjectFile);

            foreach (var asmObj in assembledObjectFiles)
            {
                config.AddAssemblyFile(asmObj as AssembledObjectFile, asmObj.Settings);
            }

            var vsSettingsGroup = config.GetSettingsGroup(VSSolutionBuilder.VSSettingsGroup.ESettingsGroup.Librarian);

            (sender.Settings as VisualStudioProcessor.IConvertToProject).Convert(sender, vsSettingsGroup);

            // order only dependencies
            foreach (var required in sender.Requirements)
            {
                if (null == required.MetaData)
                {
                    continue;
                }

                var requiredProject = required.MetaData as VSSolutionBuilder.VSProject;
                if (null != requiredProject)
                {
                    config.RequiresProject(requiredProject);
                }
            }
            // any non-C module projects should be order-only dependencies
            // note: this is unlikely to happen, as StaticLibraries don't have hard 'dependencies'
            // because there is no fixed 'link' action at the end
            foreach (var dependent in sender.Dependents)
            {
                if (null == dependent.MetaData)
                {
                    continue;
                }
                if (dependent is C.CModule)
                {
                    continue;
                }
                var dependentProject = dependent.MetaData as VSSolutionBuilder.VSProject;
                if (null != dependentProject)
                {
                    config.RequiresProject(dependentProject);
                }
            }
            // however, there may be forwarded libraries, and these are useful order only dependents
            foreach (var dependent in (sender as IForwardedLibraries).ForwardedLibraries)
            {
                if (null == dependent.MetaData)
                {
                    continue;
                }
                var dependentProject = dependent.MetaData as VSSolutionBuilder.VSProject;
                if (null != dependentProject)
                {
                    config.RequiresProject(dependentProject);
                }
            }
        }