public void AnalyzeLibraries(InventoryHelper helper, MFSolution solution, List<LibraryCategory> unresolved, List<LibraryCategory> removed) { Dictionary<string, MFComponent> reqLibList = new Dictionary<string, MFComponent>(); Dictionary<string, MFComponent> unresolvedTypes = new Dictionary<string, MFComponent>(); List<MFComponent> features = new List<MFComponent>(); Dictionary<string, MFComponent> preferredLibrary = new Dictionary<string, MFComponent>(); Processor proc = helper.FindProcessor(solution.Processor.Guid); libraryCategoriesField.Clear(); /// /// First add all the features and there dependencies /// if (this.IsClrProject) { foreach (MFComponent cmpFeat in featuresField) { RecurseFeatureDeps(cmpFeat, features, helper); } /// /// get debug transport /// if (solution.TransportType != null) { string key = solution.TransportType.Guid.ToLower(); foreach (MFComponent transportFeat in solution.TransportType.FeatureAssociations) { if (!features.Contains(transportFeat)) { features.Add(transportFeat); } } } } this.featuresField.Clear(); foreach (MFComponent cmpFeat in features) { Feature feat = helper.FindFeature(cmpFeat.Guid); this.featuresField.Add(cmpFeat); foreach (MFComponent cmp in feat.ComponentDependencies) { string key = cmp.Guid.ToLower(); if (cmp.ComponentType == MFComponentType.LibraryCategory) { if (!unresolvedTypes.ContainsKey(key)) { unresolvedTypes[key] = cmp; } } else if (cmp.ComponentType == MFComponentType.Library) { reqLibList[key] = cmp; RecurseLibCatDeps(cmp, unresolvedTypes, helper, false); } } } /// /// Add any required libraries before analyzing all project libraries /// foreach (Library lib in helper.GetRequiredLibraries()) { // Only add CLR libraries to CLR projects if (lib.Level == LibraryLevel.CLR && !this.IsClrProject) continue; string key = lib.Guid.ToLower(); if (!reqLibList.ContainsKey(key)) { MFComponent cmpNew = new MFComponent(MFComponentType.Library, lib.Name, lib.Guid, lib.ProjectPath); reqLibList[key] = cmpNew; RecurseLibCatDeps(cmpNew, unresolvedTypes, helper, false); } } /// /// Now add all required library categories /// foreach (LibraryCategory lc in helper.GetRequiredLibraryCategories()) { if (lc.Level == LibraryLevel.CLR && !this.isClrProjectField) continue; string key = lc.Guid.ToLower(); if (!unresolvedTypes.ContainsKey(key)) { MFComponent cmp = new MFComponent(MFComponentType.LibraryCategory, lc.Name, lc.Guid, lc.ProjectPath); unresolvedTypes[lc.Guid.ToLower()] = cmp; } } /// /// Add cloned solution's solution-dependent projects /// if (solution.m_cloneSolution != null && m_cloneProj != null) { foreach (MFComponent lib in m_cloneProj.librariesField) { // If we have already added a library for the current solution, then just add a new component to the project if (solution.m_clonedLibraryMap.ContainsKey(lib.Guid.ToUpper())) { Library newLib = solution.m_clonedLibraryMap[lib.Guid.ToUpper()]; librariesField.Add(new MFComponent(lib.ComponentType, newLib.Name, newLib.Guid, newLib.ProjectPath, lib.Conditional)); } // otherwise, create a new library based on the cloned solution's library else if (lib.ProjectPath.ToUpper().Contains("\\SOLUTIONS\\" + solution.m_cloneSolution.Name.ToUpper() + "\\")) { string name = CopyHelper.ReplaceText(lib.Name, solution.m_cloneSolution.Name, solution.Name); string path = CopyHelper.ReplaceText(lib.ProjectPath, solution.m_cloneSolution.Name, solution.Name); string guid = System.Guid.NewGuid().ToString("B").ToUpper(); // find cloned solution's library in the intventory Library l = helper.FindLibrary(lib); if (l != null) { Library l2 = new Library(); // copy and rename l.CopyTo(l2); CopyHelper.Rename(l2, solution.m_cloneSolution.Name, solution.Name); l2.Name = name; l2.Guid = guid; l2.ProjectPath = path; // add library to inventory helper.AddLibraryToInventory(l2, false, helper.DefaultInventory); // hash to used so that we don't add multiple libraries for each project solution.m_clonedLibraryMap[lib.Guid.ToUpper()] = l2; // Add the component to this projects library list MFComponent newCmp = new MFComponent(lib.ComponentType, name, guid, path, lib.Conditional); librariesField.Add(newCmp); if (l.HasLibraryCategory) { preferredLibrary[l.LibraryCategory.Guid.ToLower()] = newCmp; } } } } } /// /// HACK - fix this to make it data driven (add a field on library categories that allows them to be required by a solution) /// if (this.isClrProjectField) { LibraryCategory lc = helper.FindLibraryCategoryByName("WearLeveling_HAL"); if (lc != null) { string key = lc.Guid.ToLower(); if (unresolvedTypes.ContainsKey(key)) { solution.m_solRequiredLibCats[key] = unresolvedTypes[key]; } } } else if(solution.m_solRequiredLibCats != null) { foreach (MFComponent cmp in solution.m_solRequiredLibCats.Values) { string key = cmp.Guid.ToLower(); if (!unresolvedTypes.ContainsKey(key)) { unresolvedTypes[key] = cmp; } } } /// /// Use a copy of the libraries, because the libraryField may be updated inside the loop /// MFComponent[] __libs = new MFComponent[librariesField.Count]; librariesField.CopyTo(__libs); List<MFComponent> libs = new List<MFComponent>(__libs); Dictionary<string, MFComponent> resolvedTypes = new Dictionary<string, MFComponent>(); List<string> duplicateLibList = new List<string>(); while (true) { List<MFComponent> remList = new List<MFComponent>(); Dictionary<string, MFComponent> newUnresolvedTypes = new Dictionary<string, MFComponent>(); foreach (MFComponent cmpLib in libs) { Library lib = helper.FindLibrary(cmpLib); bool fKeepingLib = false; if (duplicateLibList.Contains(cmpLib.Guid.ToLower()) || lib == null || !ValidateLibrary(lib, solution, proc, helper)) { librariesField.Remove(cmpLib); remList.Add(cmpLib); continue; } if (lib.HasLibraryCategory) { if (preferredLibrary.ContainsKey(lib.LibraryCategory.Guid.ToLower()) && string.Compare(cmpLib.Guid, preferredLibrary[lib.LibraryCategory.Guid.ToLower()].Guid, true) != 0) { fKeepingLib = true; } /// /// Make sure the library selection matches the feature selection /// else if (this.isClrProjectField) { LibraryCategory lc = helper.FindLibraryCategory(lib.LibraryCategory.Guid); if (lc != null) { if (lc.FeatureAssociations.Count > 0) { bool fFeatureSelected = false; foreach (MFComponent feat in lc.FeatureAssociations) { if (features.Contains(feat)) { fFeatureSelected = true; break; } } if (((!fFeatureSelected && !lib.IsStub) || (fFeatureSelected && lib.IsStub)) && string.IsNullOrEmpty(cmpLib.Conditional)) { librariesField.Remove(cmpLib); remList.Add(cmpLib); continue; } } } } if (!fKeepingLib) { string key = lib.LibraryCategory.Guid.ToLower(); if (unresolvedTypes.ContainsKey(key) || (!string.IsNullOrEmpty(cmpLib.Conditional) && resolvedTypes.ContainsKey(key))) { unresolvedTypes.Remove(key); resolvedTypes[key] = lib.LibraryCategory; fKeepingLib = true; RecurseLibCatDeps(cmpLib, newUnresolvedTypes, helper, true); } } } else { fKeepingLib = true; } if (fKeepingLib) { remList.Add(cmpLib); duplicateLibList.Add(cmpLib.Guid.ToLower()); foreach (MFComponent dep in lib.Dependencies) { if (dep.ComponentType == MFComponentType.Library) { if (duplicateLibList.Contains(dep.Guid.ToLower()) || librariesField.Contains(dep)) { continue; } Library libDep = helper.FindLibrary(dep); if (libDep != null && libDep.HasLibraryCategory) { string key = libDep.LibraryCategory.Guid.ToLower(); if(!unresolvedTypes.ContainsKey(key) && !resolvedTypes.ContainsKey(key) && !newUnresolvedTypes.ContainsKey(key)) { newUnresolvedTypes[key] = libDep.LibraryCategory; } } else { remList.Add(dep); librariesField.Add(dep); } } } } } foreach (MFComponent cmp in remList) { if (libs.Contains(cmp)) { libs.Remove(cmp); } } if (newUnresolvedTypes.Count == 0) break; foreach (string key in newUnresolvedTypes.Keys) { if (!unresolvedTypes.ContainsKey(key) && !resolvedTypes.ContainsKey(key)) { unresolvedTypes[key] = newUnresolvedTypes[key]; } } } foreach (MFComponent cmp in resolvedTypes.Values) { libraryCategoriesField.Add(cmp); } foreach (MFComponent cmp in libs) { librariesField.Remove(cmp); } foreach (MFComponent cmp in reqLibList.Values) { if (!librariesField.Contains(cmp)) { Library lib = helper.FindLibrary(cmp); if (lib != null && ValidateLibrary(lib, solution, proc, helper)) { librariesField.Add(cmp); } } } foreach (MFComponent cmp in unresolvedTypes.Values) { LibraryCategory lc = helper.FindLibraryCategory(cmp.Guid); unresolved.Add(lc); } }
private void RecurseLibCatDeps( MFComponent cmp, Dictionary<string, MFComponent> unresolvedCatList, InventoryHelper helper, bool fDependency) { string key = cmp.Guid.ToLower(); if (unresolvedCatList.ContainsKey(key)) return; if (cmp.ComponentType == MFComponentType.Library) { Library lib = helper.FindLibrary(cmp); if (lib != null) { foreach (MFComponent dep in lib.Dependencies) { RecurseLibCatDeps(dep, unresolvedCatList, helper, true); } } } else if (cmp.ComponentType == MFComponentType.LibraryCategory) { if (!unresolvedCatList.ContainsKey(key)) { unresolvedCatList[key] = cmp; } } }