/**
         * returns a set of projects that a combine contains and a set of projects
         * that are referenced from combine projects but not part of the combine
         */
        void GetAllProjects(SolutionFolder folder, SolutionConfiguration config, out Set <SolutionItem> projects, out Set <SolutionItem> references)
        {
            List <SolutionItem> subitems = new List <SolutionItem> ();

            GetSubItems(subitems, folder);

            projects = (Set <SolutionItem>)combineProjects [folder];
            if (projects != null)
            {
                references = (Set <SolutionItem>)combineReferences [folder];
                return;
            }

            projects   = new Set <SolutionItem>();
            references = new Set <SolutionItem>();

            foreach (SolutionItem item in subitems)
            {
                if (item is SolutionEntityItem)
                {
                    SolutionEntityItem entry = (SolutionEntityItem)item;
                    if (!config.BuildEnabledForItem(entry))
                    {
                        continue;
                    }
                    projects.Add(entry);
                    references.Union(entry.GetReferencedItems(config.Selector));
                }
                else if (item is SolutionFolder)
                {
                    Set <SolutionItem> subProjects;
                    Set <SolutionItem> subReferences;
                    GetAllProjects((SolutionFolder)item, config, out subProjects, out subReferences);
                    projects.Union(subProjects);
                    references.Union(subReferences);
                }
            }

            references.Without(projects);
            combineProjects [folder]   = projects;
            combineReferences [folder] = references;
        }
        // utility function for finding the correct order to process directories
        List <SolutionItem> CalculateSubDirOrder(AutotoolsContext ctx, SolutionFolder folder, SolutionConfiguration config)
        {
            List <SolutionItem> resultOrder     = new List <SolutionItem>();
            Set <SolutionItem>  dependenciesMet = new Set <SolutionItem>();
            Set <SolutionItem>  inResult        = new Set <SolutionItem>();

            // We don't have to worry about projects built in parent combines
            dependenciesMet.Union(ctx.GetBuiltProjects());

            bool   added;
            string notMet;

            do
            {
                added  = false;
                notMet = null;

                List <SolutionItem> items = new List <SolutionItem> ();
                GetSubItems(items, folder);

                foreach (SolutionItem item in items)
                {
                    Set <SolutionItem> references, provides;

                    if (inResult.Contains(item))
                    {
                        continue;
                    }

                    if (item is SolutionEntityItem)
                    {
                        SolutionEntityItem entry = (SolutionEntityItem)item;
                        if (!config.BuildEnabledForItem(entry))
                        {
                            continue;
                        }

                        references = new Set <SolutionItem> ();
                        provides   = new Set <SolutionItem>();
                        references.Union(entry.GetReferencedItems(config.Selector));
                        provides.Add(entry);
                    }
                    else if (item is SolutionFolder)
                    {
                        GetAllProjects((SolutionFolder)item, config, out provides, out references);
                    }
                    else
                    {
                        continue;
                    }

                    if (dependenciesMet.ContainsSet(references))
                    {
                        resultOrder.Add(item);
                        dependenciesMet.Union(provides);
                        inResult.Add(item);
                        added = true;
                    }
                    else
                    {
                        notMet = item.Name;
                    }
                }
            } while (added);

            if (notMet != null)
            {
                throw new Exception("Impossible to find a solution order that satisfies project references for '" + notMet + "'");
            }

            return(resultOrder);
        }