string FindBuildDependencies(string pkgname, string config, string configs, string group, bool toplevel, bool autoExploreMode, Project parentProject) { if (parentProject == null) { parentProject = Project; } string currGroup = group; // this variable is here because group might be 'all' or 'allall', which means we will run for more than one group if(toplevel && (group == "all" || group == "allall")) { currGroup = "runtime"; // if all or allall, run "runtime" first for top level package } else if(group == "allall") { currGroup = "runtime"; // only do the same to dependent package as toplevel package if 'allall' is specified. } EAPackage eapackage; if(_packages.Contains(pkgname)) { eapackage = (EAPackage) _packages[pkgname]; if(eapackage.UpdatePackageConfigs(config)) { _packages[pkgname] = eapackage; } else if(((Hashtable)eapackage.dependents[currGroup]) != null) { if(((string)((Hashtable)eapackage.dependents[currGroup])[config]) != null) { return (string) ((Hashtable)eapackage.dependents[currGroup])[config]; } else { return ""; } } else { return ""; } } else { eapackage = new EAPackage(); eapackage.pkgName = pkgname; eapackage.autoBuildClean = true; eapackage.crossConfigs = ""; eapackage.nativeConfigs = ""; eapackage.slnTarget = null; eapackage.groupModules = new Hashtable(); eapackage.UpdatePackageConfigs(config); _packages.Add(pkgname, eapackage); } EA.FrameworkTasks.NAntTask nantTask; Project nestedProject; // If we are already in the context of the current config for top level package, just execute the target // to save some time since instantiating and running a nantTask is time-consuming if(Project.Properties["config"] == config && toplevel && PackageList == "") { nantTask = null; ProjectTargetFind(Project, currGroup + "_builddependencies").Copy().Execute(); nestedProject = Project; } else { nantTask = CreateNantTask(pkgname, currGroup + "_builddependencies", config, configs, true, parentProject); nantTask.ExecuteTaskNoDispose(); nestedProject = nantTask.NestedProject; } nestedProject.Properties["package." + pkgname + ".slngeneratormode"] = "true"; CallVcprojPrebuildTarget(nestedProject); // Find out whether this package + config has any runtime module defined CatchZeroModulePackage(pkgname, config, nestedProject); // Save the current project for generating vcproj and solutions later _projects[pkgname + "_" + config] = nestedProject; // Initialization for per package properties when the EAPackage object gets first created. if(eapackage.crossOnly == null && eapackage.nativeOnly == null) { // Find out if the package is cross-only or native-only or neither if(nestedProject.Properties.Contains("rwconfig.cross-only")) { eapackage.crossOnly = nestedProject.Properties["rwconfig.cross-only"]; } else { eapackage.crossOnly = ""; } if(nestedProject.Properties.Contains("rwconfig.native-only")) { eapackage.nativeOnly = nestedProject.Properties["rwconfig.native-only"]; } else { eapackage.nativeOnly = ""; } // For backward compatibility with rwconfig 1.x if(nestedProject.Properties.Contains("rwconfig.is-use-default-targets")) { if(nestedProject.Properties.Contains("rwconfig.enableslngeneration")) { if(nestedProject.Properties["rwconfig.enableslngeneration"].ToLower() != "true") { if(nestedProject.Properties["rwconfig.is-use-default-targets"].ToLower() == "true") { eapackage.slnTarget = TARGET_GENERATE_SLN_ALL; } } } else if(nestedProject.Properties["rwconfig.is-use-default-targets"].ToLower() == "true") { eapackage.slnTarget = TARGET_GENERATE_SLN_ALL; } } // See if the package is autobuildable eapackage = CheckPackageAutoBuildability(eapackage); _packages[pkgname] = eapackage; } // Let top level project know about all dependents' build directory and package directory in order to find all solution and vcproj files later Project.Properties["package." + pkgname + ".dir." + config] = nestedProject.Properties["package.dir"]; Project.Properties["package." + pkgname + ".builddir." + config] = nestedProject.Properties["package.builddir"]; // need to save this property as well for merged projects Project.Properties["package." + pkgname + ".builddir"] = nestedProject.Properties["package.builddir"]; string needRunCrossConfig = "false"; string dependentPackagesNeedExploreCross = ""; string exploredIndirectBuilddependentList = ""; // Prepare all properties that are used to be put in initialize.xml because slnmaker needs to know // these properties. PopulateInitializeProperties(config, pkgname, nestedProject); // Get all info about the dependent runtime buildmodules that the current package depends on. // This is to tell slnmaker to not include project dependencines on unused modules. string bms = GetUnProcessedBuildModules(nestedProject, currGroup, config); PopulateDependentBuildModules(config, currGroup, nestedProject, ref needRunCrossConfig, ref dependentPackagesNeedExploreCross, ref exploredIndirectBuilddependentList, bms); string builddependentlist = GetBuildDependentList(nestedProject, currGroup, bms); // examine all new explored build dependents' initialize.xml DoDependentTaskOnPackages(nestedProject, builddependentlist); builddependentlist = CombineStrings(builddependentlist, exploredIndirectBuilddependentList); eapackage.UpdateDependents(builddependentlist.Trim(), config, currGroup); _packages[pkgname] = eapackage; string groupPassedDown = "runtime"; if(toplevel || ((group == "allall") && (!toplevel))) { // Get all build dependents for all groups for current package and current config foreach(string grp in _groups) { if(grp != currGroup) { bms = GetUnProcessedBuildModules(nestedProject, grp, config); exploredIndirectBuilddependentList = ""; PopulateDependentBuildModules(config, grp, nestedProject, ref needRunCrossConfig, ref dependentPackagesNeedExploreCross, ref exploredIndirectBuilddependentList, bms); string groupbuilddependentlist = GetBuildDependentList(nestedProject, grp, bms); // examine all new explored build dependents' initialize.xml DoDependentTaskOnPackages(nestedProject, groupbuilddependentlist); builddependentlist = CombineStrings(builddependentlist, exploredIndirectBuilddependentList); builddependentlist = CombineStrings(builddependentlist, groupbuilddependentlist);//nestedProject.Properties[PROPERTY_BUILD_DEPENDENCIES]); eapackage.UpdateDependents(builddependentlist, config, grp); _packages[pkgname] = eapackage; } } if(group == "allall") groupPassedDown = group; } string fullDependentList = ""; // this will be returned to parent package. if(builddependentlist.Trim() != string.Empty) { foreach(string dependent in NantToVSTools.TrimAndSplit(builddependentlist)) { // If the dependent is framework 1.0 package, we dont proceed anymore. if(nestedProject.Properties["package." + dependent + ".frameworkversion"] == "1") continue; // Do not proceed if the dependent package is set autobuildclean = false. // Also check whether dependent is forced to be cross only or native only package and then see whether to proceed or not // for the current config (here cross/native only doesn't mean dependent is cross/native-only package.) if(! ProceedConfigForPackage(dependent, config)) { if(_properties.Contains("package." + dependent + ".autobuildclean")) { if(((string)_properties["package." + dependent + ".autobuildclean"]) == "false") { nestedProject.Properties["package." + dependent + ".autobuildclean"] = "false"; _projects[pkgname + "_" + config] = nestedProject; } } continue; } AddPackageProperties(dependent); string deplist = FindBuildDependencies(dependent, config, configs, groupPassedDown, false, false, nestedProject); if(deplist != "") { eapackage.ExpandDependent(dependent, deplist, config); _packages[pkgname] = eapackage; } } // Normally we only return runtime group dependents, but when auto-exploring is on, we need to get all dependents from all groups. if(autoExploreMode) { // we only need to return dependents from all groups when the follwoing condition is true. if(toplevel || ((group == "allall") && (!toplevel))) { foreach(string grp in _groups) { fullDependentList = CombineStrings(fullDependentList, (string) ((Hashtable)eapackage.dependents[grp])[config]); } } else fullDependentList = CombineStrings(fullDependentList, (string) ((Hashtable)eapackage.dependents[currGroup])[config]); } else { fullDependentList = CombineStrings(fullDependentList, (string) ((Hashtable)eapackage.dependents[currGroup])[config]); } } // if we are in native config and we found native module depends on cross module, it means we need to run cross config as well if(config.IndexOf("cross") == -1) { // we found native module in one package depend on cross module in other package if(dependentPackagesNeedExploreCross != "") { string crossConfig = nestedProject.Properties["config-cross"] + "-" + nestedProject.Properties["config-name"]; foreach(string deppkg in NantToVSTools.TrimAndSplit(dependentPackagesNeedExploreCross)) { if(ProceedConfigForPackage(deppkg, crossConfig)) { string plist = FindBuildDependencies(deppkg, crossConfig, configs, groupPassedDown, false, true, null); foreach(string dpkg in NantToVSTools.TrimAndSplit(plist + " " + deppkg)) { if(_packages.Contains(dpkg)) { EAPackage eadpkg = (EAPackage) _packages[dpkg]; eadpkg.UpdateExploredCrossConfigs(config, crossConfig); _packages[dpkg] = eadpkg; // Add this cross config into package.configs unless it's there already string pConfigs = Project.Properties["package.configs"]; if(! ListContainsString(pConfigs, crossConfig)) Project.Properties.UpdateReadOnly("package.configs", pConfigs + " " + crossConfig); } } } } } if(needRunCrossConfig == "true") { string crossConfig = nestedProject.Properties["config-cross"] + "-" + nestedProject.Properties["config-name"]; if(! ListContainsString(eapackage.crossConfigs, crossConfig)) // if this cross config hasn't been run yet { if(ProceedConfigForPackage(pkgname, crossConfig)) { string plist = FindBuildDependencies(pkgname, crossConfig, configs, group, toplevel, true, null); foreach(string dpkg in NantToVSTools.TrimAndSplit(plist)) { if(_packages.Contains(dpkg)) { EAPackage eadpkg = (EAPackage) _packages[dpkg]; eadpkg.UpdateExploredCrossConfigs(config, crossConfig); _packages[dpkg] = eadpkg; } } eapackage = (EAPackage)_packages[eapackage.pkgName]; eapackage.UpdateExploredCrossConfigs(config, crossConfig); // Add this cross config into package.configs unless it's there already string pConfigs = Project.Properties["package.configs"]; if(! ListContainsString(pConfigs, crossConfig)) Project.Properties.UpdateReadOnly("package.configs", pConfigs + " " + crossConfig); } } } } if(nantTask != null) { // remove the reference to nantTask.nestedProject nestedProject.Dispose(); nestedProject = null; nantTask.NestedProject.Dispose(); nantTask.NestedProject = null; nantTask.Project = null; nantTask = null; } _packages[pkgname] = eapackage; return fullDependentList; }
void Vcproj(EAPackage eapkg, string cfg) { // if nantProject is not null, it means that it needs to run generate-sln-all target instead // of the rwconfig-2.0 workflow. if(eapkg.slnTarget != null) return; // if the package is not autobuildable, then just return if(eapkg.autoBuildClean == false) return; if(eapkg.crossOnly == "true" && eapkg.nativeOnly == "true") throw new BuildException(eapkg.pkgName + ": rwconfig.native-only and rwconfig.cross-only can not both be set to true"); string configs = cfg; if(cfg.IndexOf("cross") == -1) // if the current config is native { string crossconfig = eapkg.GetExploredCrossConfig(cfg); if(crossconfig == "")// if no explored cross config, then treat it as usual { if(eapkg.crossOnly == "true") return; if(! ListContainsString(eapkg.nativeConfigs, cfg)) return; } else { if(eapkg.crossOnly == "true" || ! ListContainsString(eapkg.nativeConfigs, cfg)) configs = crossconfig; else configs = cfg + " " + crossconfig; } } if(eapkg.nativeOnly == "true" && cfg.IndexOf("cross") != -1) return; if(cfg.IndexOf("cross") != -1 && ! ListContainsString(eapkg.crossConfigs, cfg)) return; string [] groups = _groups; if(Group != "allall") { if(PackageList != "" && (! ListContainsString(PackageList, eapkg.pkgName))) { groups = new string [] {"runtime"}; } else if(eapkg.pkgName != Project.Properties["package.name"] && PackageList == "") { groups = new string [] {"runtime"}; } } Hashtable groupModules = new Hashtable(); foreach(string group in groups ) { groupModules.Add(group, new Hashtable()); if(! eapkg.groupModules.Contains(group)) { eapkg.groupModules.Add(group, new Hashtable()); } } foreach(string group in groups ) { Hashtable tempCurrModules = (Hashtable) groupModules[group]; foreach(string config in NantToVSTools.TrimAndSplit(configs)) { if(config == string.Empty) continue; // generate vsprojs for all modules of each group for current config Project proj = (Project) _projects[eapkg.pkgName + "_" + config]; if(proj == null) continue; foreach (string property in _properties.Keys) { string prop = property; if (prop.EndsWith("." + cfg + ".vsproj")) { prop = prop.Replace("." + cfg + ".vsproj", ""); proj.Properties[prop] = (string)_properties[property]; } } string constrainedBuildModules = ""; if(eapkg.pkgName != Project.Properties["package.name"]) constrainedBuildModules = (string) _properties[eapkg.pkgName + "." + group + ".buildmodules." + config]; string buildModules = eapkg.pkgName; if(group != "runtime") buildModules = group + "-" + buildModules; string supressedBuildModules = ""; if(proj.Properties.Contains(group + ".buildmodules")) { if(constrainedBuildModules == "" || constrainedBuildModules == null) buildModules = proj.Properties[group + ".buildmodules"]; else buildModules = SortConstrainedBuildModules(constrainedBuildModules, proj.Properties[group + ".buildmodules"], ref supressedBuildModules); } else if(! proj.Properties.Contains(group + ".buildtype") && ! proj.Properties.Contains(group + ".builddependencies")) { // zero module continue; } string tempModulesString = ""; ArrayList cSharpModules = new ArrayList(); ArrayList managedCPPModules = new ArrayList(); foreach(string module in NantToVSTools.TrimAndSplit(buildModules)) { if(module != string.Empty) { string moduleKey = module; if (group != "runtime" && moduleKey == group + "-" + eapkg.pkgName) { moduleKey = eapkg.pkgName; } ManagedModule mm = _managedmodulelist.Find(eapkg.pkgName + "*" + config + "*" + moduleKey + "*" + group); string tempModule = module; if(module == String.Empty) continue; // if it is a cross config, then we need to add cross- prefix to the module name if(config.ToLower().IndexOf("cross") != -1) { if(! module.StartsWith("cross-")) { proj.Properties.Add(module + ".vcproj-name-cross", "cross-" + module); _properties[eapkg.pkgName + "." + module + ".vcproj-name-cross." + config] = "cross-" + module; tempModule = "cross-" + module; } } string buildtype = (string) proj.Properties[group + "." + module + ".buildtype"]; if(buildtype == null) buildtype = (string) proj.Properties[group + ".buildtype"]; if(buildtype != null) { if (mm == null || (!mm.IsCSharp)) // not a CSharp module { if (mm != null && (!mm.IsCSharp)) managedCPPModules.Add(mm); Hashtable currModules = (Hashtable)eapkg.groupModules[group]; // check duplicate module names in other groups foreach (string othergroup in groups) { if (othergroup != group) { if (((Hashtable)eapkg.groupModules[othergroup]).Contains(tempModule)) { string errorString = String.Format("Error: Found duplicated module name {0} between groups {1} and {2} in package {3}", tempModule, group, othergroup, eapkg.pkgName); throw new BuildException(errorString); } } } // save each config for the module for the final merge step if (currModules.Contains(tempModule)) { // if two configs are the same, it means this module+config already been generated before. this only applies to cross modules that have native module depend on it if (!ListContainsString(((string)currModules[tempModule]), config)) { currModules[tempModule] = ((string)currModules[tempModule]) + " " + config; tempCurrModules[tempModule] = config; tempModulesString = tempModulesString + module + " "; } } else { currModules[tempModule] = config; tempCurrModules[tempModule] = config; // this is for merging only this config tempModulesString = tempModulesString + module + " "; } eapkg.groupModules[group] = currModules; groupModules[group] = tempCurrModules; } else // found CSharp module { cSharpModules.Add(mm); } } } } proj.Properties[PROPERTY_SKIP_BUILD_NANTTOVSTOOLS] = "true"; if (proj.Properties.Contains(group + ".buildmodules")) { proj.Properties[group + ".buildmodules.temp"] = proj.Properties[group + ".buildmodules"]; } // Always check if there are any CSharp modules if (cSharpModules.Count != 0) { //Copy project into backup location for slnmerger. foreach (ManagedModule mmodule in cSharpModules) // remove projectreference optionsets { if (IsBuildingEasharpCSC(proj)) continue; if (File.Exists(mmodule.VSProjLocation) && !File.Exists(mmodule.VSProjLocation + ".backup")) { File.Copy(mmodule.VSProjLocation, mmodule.VSProjLocation+".backup", true); // save it for merge step } } string cSharpModulesString = ""; foreach (ManagedModule mmodule in cSharpModules) // add projectreference optionsets { cSharpModulesString = CombineStrings(cSharpModulesString, mmodule.Module); if (mmodule.ProjRefCount != 0) { mmodule.SetProjRefOptionSet(proj); } } if (proj.Properties.Contains(group + ".buildmodules")) { proj.Properties[group + ".buildmodules"] = cSharpModulesString; } proj.Properties[group + ".supressedBuildModules"] = supressedBuildModules; if (group == "runtime") ProjectTargetFind(proj, TARGET_CSPROJ).Copy().Execute(); else ProjectTargetFind(proj, TARGET_CSPROJ + group).Copy().Execute(); if (proj.Properties.Contains(group + ".buildmodules")) { // restore group.buildmodules properties proj.Properties[group + ".buildmodules"] = proj.Properties[group + ".buildmodules.temp"]; } foreach (ManagedModule mmodule in cSharpModules) // remove projectreference optionsets { if (IsBuildingEasharpCSC(proj)) continue; string configVsprojFileLocation = Path.GetDirectoryName(mmodule.VSProjLocation) + Path.DirectorySeparatorChar + config + Path.DirectorySeparatorChar + Path.GetFileName(mmodule.VSProjLocation); Directory.CreateDirectory(Path.GetDirectoryName(mmodule.VSProjLocation) + Path.DirectorySeparatorChar + config); File.Copy(mmodule.VSProjLocation, configVsprojFileLocation, true); // save it for merge step if (File.Exists(mmodule.VSProjLocation + ".user")) File.Copy(mmodule.VSProjLocation + ".user", configVsprojFileLocation + ".user", true); if (mmodule.ProjRefCount != 0) mmodule.RemoveProjRefOptionSet(proj); } cSharpModules.Clear(); } if(tempCurrModules.Count != 0) // make sure to only generate the same module+config once { foreach (ManagedModule mmodule in managedCPPModules) // add projectreference optionsets { if (mmodule.ProjRefCount != 0) { mmodule.SetProjRefOptionSet(proj); } } if(proj.Properties.Contains(group + ".buildmodules")) { proj.Properties[group + ".buildmodules"] = tempModulesString; } proj.Properties["eaconfig.build.target"] = "eaconfig-vcproj"; proj.Properties["eaconfig.build.group"] = group; proj.Targets.Find("eaconfig-build-caller").Copy().Execute(); if(proj.Properties.Contains(group + ".buildmodules")) { // restore group.buildmodules properties proj.Properties[group + ".buildmodules"] = proj.Properties[group + ".buildmodules.temp"]; } foreach (ManagedModule mmodule in managedCPPModules) // remove projectreference optionsets { if (mmodule.ProjRefCount != 0) { mmodule.RemoveProjRefOptionSet(proj); } } managedCPPModules.Clear(); } if (proj.Properties.Contains(group + ".buildmodules")) { proj.Properties.Remove(group + ".buildmodules.temp"); } proj = null; } } if (IsBuildingEasharpCSC(Project)) { return; } // if only generating for one config, we don't do the merge step but should store the vcprojs' locations // for slnmaker to use later on. if(Project.Properties.Contains("generate-single-config")) { foreach(string grp in groupModules.Keys) { foreach(string mod in ((Hashtable) groupModules[grp]).Keys) { string groupDir = ""; if(grp != "runtime") groupDir = Path.DirectorySeparatorChar + grp; string currentconfig = (string) ((Hashtable) groupModules[grp])[mod]; string property = eapkg.pkgName + "." + mod + ".vcprojlocation." + currentconfig; string propertyValue = Project.Properties["package." + eapkg.pkgName + ".builddir"] + Path.DirectorySeparatorChar + currentconfig + Path.DirectorySeparatorChar + "build" + groupDir + Path.DirectorySeparatorChar + mod + ".vcproj"; _properties[property] = propertyValue; // if we are in native config but need cross module, we need to store that cross module's vsprojlocation in native config as well so that // slnmaker can find it when generating sln for native configs. if(currentconfig != cfg) _properties[eapkg.pkgName + "." + mod + ".vcprojlocation." + cfg] = propertyValue; } } } else { // We need to copy the vcproj file to the package.builddir where slnmaker looks for vcproj files. foreach(string grp in groupModules.Keys) { foreach(string mod in ((Hashtable) groupModules[grp]).Keys) { string groupDir = ""; if(grp != "runtime") groupDir = Path.DirectorySeparatorChar + grp; string config = (string) ((Hashtable) groupModules[grp])[mod]; string vcprojfilelocation = Project.Properties["package." + eapkg.pkgName + ".builddir." + config] + Path.DirectorySeparatorChar + config + Path.DirectorySeparatorChar + "build" + groupDir + Path.DirectorySeparatorChar + mod + ".vcproj"; string finalvcprojfilelocation = Project.Properties["package." + eapkg.pkgName + ".builddir." + config] + Path.DirectorySeparatorChar + mod + ".vcproj"; // a hack for pc-vc-tools config if (IsToolConfigBuild(Project.Properties["package.configs"])) { if (config.IndexOf("vc-tool-") == -1) { continue; } string ext = Path.GetExtension(finalvcprojfilelocation); if (ext == ".vcproj" || ext == ".csproj") { string fn = Path.GetFileNameWithoutExtension(finalvcprojfilelocation); string dir = Path.GetDirectoryName(finalvcprojfilelocation); finalvcprojfilelocation = Path.Combine(dir, fn + "-tools" + ext); } } File.Copy(vcprojfilelocation, finalvcprojfilelocation, true); } } } _packages[eapkg.pkgName] = eapkg; }
EAPackage CheckPackageAutoBuildability(EAPackage eapkg) { // It doesn't make sense to check top level package's autobuildability if(eapkg.pkgName != Project.Properties["package.name"]) { string masterVersion = PackageMap.Instance.GetMasterVersion(eapkg.pkgName, Project); if (masterVersion == null) { string msg = string.Format("ERROR: You must specify a version for package '{0}' in your masterconfig.xml file.", eapkg.pkgName); throw new BuildException(msg, Location); } Release info = PackageMap.Instance.Releases.FindByNameAndVersion(eapkg.pkgName, masterVersion); if(info.AutoBuildClean.ToLower() == "false") { eapkg.autoBuildClean = false; } } return eapkg; }
void SlnMaker(EAPackage eapkg, string cfg) { // if slnTarget is not null, it means that it needs to run generate-sln-all target instead // of the rwconfig-2.0 workflow. This is for backward compatibility with rwconfig 1.x if(eapkg.slnTarget != null) return; // if the package is not autobuildable, then just return if(eapkg.autoBuildClean == false) return; string configs = cfg; if(cfg.IndexOf("cross") == -1) // if the current config is native { string crossconfig = eapkg.GetExploredCrossConfig(cfg); if(crossconfig == "") { if(eapkg.crossOnly == "true") return; if(! ListContainsString(eapkg.nativeConfigs, cfg)) return; } else { // if found native-dependon-cross config, and package.configs doesn't contain this cross config // then it means no more constrain-on-buildmodules gathering operation, we can make sln for this cross config now. if(! ListContainsString(originalPackageConfigs, crossconfig)) { if(eapkg.crossOnly == "true" || ! ListContainsString(eapkg.nativeConfigs, cfg)) configs = crossconfig; else configs = cfg + " " + crossconfig; } else // if package.configs contains this cross config, then we hold this cross config because there might be more buildmodule-constrains gathering { if(eapkg.crossOnly == "true" || ! ListContainsString(eapkg.nativeConfigs, cfg)) return; } } } if(eapkg.nativeOnly == "true" && cfg.IndexOf("cross") != -1) return; if(cfg.IndexOf("cross") != -1 && ! ListContainsString(eapkg.crossConfigs, cfg)) return; string [] groups = _groups; if(Group != "allall") { if(PackageList != "" && (! ListContainsString(PackageList, eapkg.pkgName))) { groups = new string [] {"runtime"}; } else if(eapkg.pkgName != Project.Properties["package.name"] && PackageList == "") { groups = new string [] {"runtime"}; } } foreach(string config in NantToVSTools.TrimAndSplit(configs)) { if(config == string.Empty) continue; Project proj = (Project) _projects[eapkg.pkgName + "_" + config]; if(proj == null && config.IndexOf("cross") != -1) // the sln for this cross config has already been generated. continue; string packageBuilddir = proj.Properties["package.builddir"]; foreach(string grp in groups) { proj.Properties["package.nantToVSTools.slnmaker.default.output"] = packageBuilddir + "\\" + config + "\\" + eapkg.pkgName + "_" + grp + ".sln"; // Get all initialize.xml properties for all relevant packages and all other relevant properties for slnmaking. foreach(object property in _properties.Keys) { string prop = (string) property; if(prop.EndsWith("." + config)) { prop = prop.Replace("." + config, ""); proj.Properties[prop] = (string) _properties[property]; } } if(Project.Properties.Contains("generate-single-config")) { proj.Properties["generate-single-config"] = "true"; } ProjectTargetFind(proj, "sln" + grp + "-slnmaker").Copy().Execute(); AddSlnToFileSets(eapkg.pkgName, grp, packageBuilddir + "\\" + config + "\\" + eapkg.pkgName + "_" + grp + ".sln"); } _projects[eapkg.pkgName + "_" + config] = null; if(eapkg.pkgName != Project.Properties["package.name"] || (eapkg.pkgName == Project.Properties["package.name"] && config != Project.Properties["config"])) { proj.Dispose(); proj = null; } } }