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; }