Beispiel #1
0
        // Populates configSection.DeployFileVars with unique DeployFiles for a particular config
        void ProcessDeployFilesForConfig(DeployFileCollection deployFiles, Project project, ConfigSection configSection, AutotoolsContext ctx, DotNetProjectConfiguration config)
        {
            //@deployFiles can have duplicates
            Dictionary <string, DeployFile> uniqueDeployFiles = new Dictionary <string, DeployFile> ();

            foreach (DeployFile dfile in deployFiles)
            {
                if (dfile.SourcePath == project.GetOutputFileName(configSection.Selector))
                {
                    continue;
                }

                // DeployFileCollection can have duplicates, ignore them
                string key = dfile.RelativeTargetPath;
                if (!dfile.ContainsPathReferences)
                {
                    key += dfile.SourcePath;
                }
                if (uniqueDeployFiles.ContainsKey(key))
                {
                    continue;
                }
                uniqueDeployFiles [key] = dfile;

                string targetDeployVar = GetDeployVar(deployFileVars, dfile.RelativeTargetPath);
                configSection.DeployFileVars [targetDeployVar] = dfile;
                DeployFileData data = new DeployFileData();
                data.File          = dfile;
                data.Configuration = config;
                allDeployVars [targetDeployVar] = data;
            }
        }
		public Makefile Deploy (AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor)
		{
			generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile;
			
			monitor.BeginTask ( GettextCatalog.GetString (
						"Creating {0} for Project {1}",
						generateAutotools ? "Makefile.am" : "Makefile", entry.Name), 1 );
			
			Makefile makefile = new Makefile ();
			try
			{
				if ( !CanDeploy (entry, generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile) ) 
					throw new Exception ( GettextCatalog.GetString ("Not a deployable project.") );

				Project project = entry as Project;
				TemplateEngine templateEngine = new TemplateEngine();			
				ISimpleAutotoolsSetup setup = FindSetupForProject ( project );

				// Handle files to be deployed
				deployDirs = new Dictionary<string, StringBuilder> ();
				deployFileVars = new Dictionary<string, string> ();
				builtFiles = new List<string> ();
				deployFileCopyVars = new StringBuilder ();
				deployFileCopyTargets = new StringBuilder ();

				//used only for simple makefile generation
				templateFilesTargets = null;
				installTarget = null;
				installDeps = null;
				installDirs = null;
				uninstallTarget = null;

				// handle configuration specific variables
				conf_vars = new StringBuilder ();

				// grab all project files
				files = new StringBuilder ();
				res_files = new StringBuilder ();
				extras = new StringBuilder ();
				datafiles = new StringBuilder ();
				Set<string> extraFiles = new Set<string> ();

				string includes = String.Empty;
				string references, dllReferences;
				DotNetProject netProject = project as DotNetProject;
				ProcessProjectReferences (netProject, out references, out dllReferences, ctx);

				templateEngine.Variables["REFERENCES"] = references;
				templateEngine.Variables["DLL_REFERENCES"] =  dllReferences;
				templateEngine.Variables["WARNING"] = "Warning: This is an automatically generated file, do not edit!";

				DotNetProject dotnetProject = entry as DotNetProject;
				if (dotnetProject != null)
				{
					string resgen = "resgen";
					if (System.Environment.Version.Major >= 2) {
						switch (dotnetProject.TargetFramework.ClrVersion) {
							case ClrVersion.Net_1_1: resgen = "resgen1"; break;
							default: resgen = "resgen2"; break;
						}
					}
					templateEngine.Variables ["RESGEN"] = resgen;
				}
				
				string pfpath = null;
				foreach (ProjectFile projectFile in project.Files) 
				{
					pfpath = FileService.NormalizeRelativePath (projectFile.FilePath.ToRelative (project.BaseDirectory));
					switch ( projectFile.BuildAction )
					{
						case BuildAction.Compile:
							
							if ( projectFile.Subtype != Subtype.Code ) continue;
							files.AppendFormat ( "\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
							break;

						case BuildAction.Content:
						case BuildAction.None:

							extraFiles.Add (MakefileData.ToMakefilePath (pfpath));
							break;

						case BuildAction.EmbeddedResource:

							if ( !projectFile.FilePath.IsChildPathOf ( ctx.BaseDirectory ) )
							{
								// file is not within directory hierarchy, copy it in
								string rdir = Path.Combine (Path.GetDirectoryName (project.FileName), resourcedir);
								if ( !Directory.Exists ( rdir ) ) Directory.CreateDirectory ( rdir );
								string newPath = Path.Combine (rdir, Path.GetFileName ( projectFile.FilePath ));
								FileService.CopyFile ( projectFile.FilePath, newPath ) ;
								pfpath = project.GetRelativeChildPath (newPath);
								pfpath = FileService.NormalizeRelativePath (pfpath);
							}
							if (!String.IsNullOrEmpty (projectFile.ResourceId) && projectFile.ResourceId != Path.GetFileName (pfpath))
								res_files.AppendFormat ("\\\n\t{0},{1} ", MakefileData.ToMakefilePath (pfpath), MakefileData.EscapeString (projectFile.ResourceId));
							else
								res_files.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
 
							break;

						case "FileCopy":

							datafiles.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (pfpath));
							break;
					}
				}

				if (!generateAutotools) {
					templateFilesTargets = new StringBuilder ();
					installTarget = new StringBuilder ();
					uninstallTarget = new StringBuilder ();
					installDeps = new StringBuilder ();
					installDirs = new List<string> ();

					customCommands = new StringBuilder ();

					string programFilesDir = ctx.DeployContext.GetDirectory (TargetDirectory.ProgramFiles);
					//FIXME:temp
					programFilesDir = TranslateDir (programFilesDir);
					installDirs.Add (programFilesDir);
					installTarget.Append ("\tmake pre-install-local-hook prefix=$(prefix)\n");
					installTarget.Append ("\tmake install-satellite-assemblies prefix=$(prefix)\n");
					installTarget.AppendFormat ("\tmkdir -p '$(DESTDIR){0}'\n", programFilesDir);
					installTarget.AppendFormat ("\t$(call cp,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
					installTarget.AppendFormat ("\t$(call cp,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

					//remove dir?
					uninstallTarget.Append ("\tmake pre-uninstall-local-hook prefix=$(prefix)\n");
					uninstallTarget.Append ("\tmake uninstall-satellite-assemblies prefix=$(prefix)\n");
					uninstallTarget.AppendFormat ("\t$(call rm,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
					uninstallTarget.AppendFormat ("\t$(call rm,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

					installDeps.Append (" $(ASSEMBLY) $(ASSEMBLY_MDB)");

					conf_vars.AppendFormat ("srcdir=.\n");
					conf_vars.AppendFormat ("top_srcdir={0}\n\n",
						FileService.AbsoluteToRelativePath (project.BaseDirectory, ctx.TargetSolution.BaseDirectory));

					conf_vars.AppendFormat ("include $(top_srcdir)/config.make\n\n");

					// Don't emit for top level project makefile(eg. pdn.make), as it would be
					// included by top level solution makefile
					if (ctx.TargetSolution.BaseDirectory != project.BaseDirectory){
						string customhooks = Path.Combine (project.BaseDirectory, "custom-hooks.make");
						bool include = File.Exists (customhooks);
					
						includes = "include $(top_srcdir)/Makefile.include\n";
						includes += String.Format ("{0}include $(srcdir)/custom-hooks.make\n\n", include ? "" : "#");
						if (include)
							makefile.SetVariable ("EXTRA_DIST", "$(srcdir)/custom-hooks.make");
					}
				}

				bool buildEnabled;
				List<ConfigSection> configSections = new List<ConfigSection> ();
				allDeployVars = new Dictionary<string, DeployFileData> ();

				foreach (SolutionConfiguration combineConfig in ctx.TargetSolution.Configurations)
				{
					DotNetProjectConfiguration config = GetProjectConfig (combineConfig.Id, project, out buildEnabled) as DotNetProjectConfiguration;
					if (config == null)
						continue;

					ConfigSection configSection = new ConfigSection (combineConfig.Id);

					string assembly = MakefileData.GetUnixPath (project.GetRelativeChildPath (config.CompiledOutputName));

					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_COMPILER_COMMAND = {0}\n",
							setup.GetCompilerCommand ( project, config.Id ) );
					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_COMPILER_FLAGS = {0}\n",
							setup.GetCompilerFlags ( project, config.Id ) );

					// add check for compiler command in configure.ac
					ctx.AddCommandCheck ( setup.GetCompilerCommand ( project, config.Id ) );

					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY = {0}\n",
						AutotoolsContext.EscapeStringForAutomake (assembly));
					configSection.BuildVariablesBuilder.AppendFormat ("ASSEMBLY_MDB = {0}\n",
						config.DebugMode ? "$(ASSEMBLY).mdb" : String.Empty);

					string target;
					switch (config.CompileTarget)
					{
						case CompileTarget.Exe:
							target = "exe";
							break;
						case CompileTarget.Library:
							target = "library";
							break;
						case CompileTarget.WinExe:
							target = "winexe";
							break;
						case CompileTarget.Module:
							target = "module";
							break;
						default:
							throw new Exception( GettextCatalog.GetString ("Unknown target {0}", config.CompileTarget ) );
					}
					configSection.BuildVariablesBuilder.AppendFormat ( "COMPILE_TARGET = {0}\n", target );

					// for project references, we need a ref to the dll for the current configuration
					StringWriter projectReferences = new StringWriter();
					string pref = null;
					foreach (ProjectReference reference in netProject.References) 
					{
						if (reference.ReferenceType != ReferenceType.Project)
							continue;
						Project refp = GetProjectFromName (reference.Reference, ctx.TargetSolution);

						if (!(refp is DotNetProject))
							continue;
						
						DotNetProjectConfiguration dnpc = GetProjectConfig (combineConfig.Id, refp, out buildEnabled) as DotNetProjectConfiguration;
						if ( dnpc == null )
							throw new Exception ( GettextCatalog.GetString
									("Could not add reference to project '{0}'", refp.Name) );

						projectReferences.WriteLine (" \\");
						projectReferences.Write ("\t");
						pref = project.GetRelativeChildPath (dnpc.CompiledOutputName);

						projectReferences.Write (MakefileData.ToMakefilePath (pref));
					}
					configSection.BuildVariablesBuilder.AppendFormat ( "PROJECT_REFERENCES = {0}\n", projectReferences.ToString() );

					string buildDir = project.GetRelativeChildPath (config.OutputDirectory);
					configSection.BuildVariablesBuilder.AppendFormat ("BUILD_DIR = {0}\n", MakefileData.ToMakefilePath (buildDir));

					// Register files built by this configuration.
					// Built files won't be distributed.
					foreach (string bfile in builtFiles)
						ctx.AddBuiltFile (Path.Combine (config.OutputDirectory, bfile));

					DeployFileCollection deployFiles = DeployService.GetDeployFiles (
							ctx.DeployContext, new SolutionItem[] { project }, config.Selector);

					ProcessDeployFilesForConfig (deployFiles, project, configSection, ctx, config);
					configSections.Add (configSection);

					if (!generateAutotools) {
						EmitCustomCommandTargets (config.CustomCommands, project, customCommands, combineConfig.Id,
								new CustomCommandType [] {
									CustomCommandType.BeforeBuild,
									CustomCommandType.AfterBuild,
									CustomCommandType.BeforeClean,
									CustomCommandType.AfterClean}, monitor);
					} else {
						if (config.CustomCommands.Count > 0)
							monitor.ReportWarning (GettextCatalog.GetString ("Custom commands are not supported for autotools based makefiles. Ignoring."));
					}

					// Register files generated by the compiler
					ctx.AddBuiltFile (project.GetOutputFileName (combineConfig.Selector));
					if (config.DebugMode)
						ctx.AddBuiltFile (project.GetOutputFileName (combineConfig.Selector) + ".mdb");

					if (config.SignAssembly) {
						string spath = project.GetRelativeChildPath (config.AssemblyKeyFile);
						spath = FileService.NormalizeRelativePath (spath);
						extraFiles.Add (MakefileData.ToMakefilePath (spath));
					}

					if (buildEnabled && pkgs.Count > 0)
						ctx.AddRequiredPackages (combineConfig.Id, pkgs);
				}


				foreach (string ef in extraFiles)
					extras.AppendFormat ("\\\n\t{0} ", ef);

				Dictionary<string, DeployFileData> commonDeployVars = new Dictionary<string, DeployFileData> (allDeployVars);
				foreach (ConfigSection configSection in configSections) {
					List<string> toRemove = new List<string> ();
					foreach (KeyValuePair<string, DeployFileData> pair in commonDeployVars) {
						if (!configSection.DeployFileVars.ContainsKey (pair.Key))
							toRemove.Add (pair.Key);
					}
					foreach (string s in toRemove)
						commonDeployVars.Remove (s);
				}

				//emit the config sections here.. to conf_vars
				foreach (ConfigSection configSection in configSections) {
					conf_vars.AppendFormat (generateAutotools ? "if ENABLE_{0}\n" : "ifeq ($(CONFIG),{0})\n",
							ctx.EscapeAndUpperConfigName (configSection.Name));

					conf_vars.Append (configSection.BuildVariablesBuilder.ToString ());
					conf_vars.Append ("\n");
					
					if (ctx.Switches != null) {
						foreach (Switch s in ctx.Switches) {
							conf_vars.AppendLine (string.Format (@"if ENABLE_{0}
ASSEMBLY_COMPILER_FLAGS += -define:{1}
endif", s.SwitchName.Replace ('-', '_').ToUpperInvariant (), s.Define));
						}
					}

					foreach (KeyValuePair<string, DeployFileData> pair in allDeployVars) {
						string targetDeployVar = pair.Key;
						if (pair.Value.File.ContainsPathReferences)
							//Template files are not handled per-config
							continue;

						if (configSection.DeployFileVars.ContainsKey (targetDeployVar)) {
							//use the dfile from the config section
							DeployFile dfile = configSection.DeployFileVars [targetDeployVar];
							string fname = MakefileData.ToMakefilePath (
									FileService.AbsoluteToRelativePath (
										Path.GetFullPath (project.BaseDirectory),
										Path.GetFullPath (dfile.SourcePath)));

							conf_vars.AppendFormat ("{0}_SOURCE={1}\n", targetDeployVar, fname);

							if (!commonDeployVars.ContainsKey (targetDeployVar)) {
								//FOO_DLL=$(BUILD_DIR)/foo.dll
								conf_vars.AppendFormat ("{0}=$(BUILD_DIR)/{1}\n",
										targetDeployVar,
										MakefileData.ToMakefilePath (dfile.RelativeTargetPath));
							}
						} else {
							// not common and not part of @configSection
							conf_vars.AppendFormat ("{0}=\n", pair.Key);
						}
					}

					conf_vars.Append ( "\nendif\n\n" );
				}

				conf_vars.AppendFormat ("AL={0}\n", (dotnetProject.TargetFramework.ClrVersion == ClrVersion.Net_2_0) ? "al2" : "al");
				conf_vars.AppendFormat ("SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll\n");

				foreach (KeyValuePair<string, DeployFileData> pair in allDeployVars) {
					HandleDeployFile (pair.Value, pair.Key, project, ctx);

					if (commonDeployVars.ContainsKey (pair.Key)) {
						//FOO_DLL=$(BUILD_DIR)/foo.dll
						deployFileCopyVars.AppendFormat ("{0} = $(BUILD_DIR)/{1}\n",
									pair.Key,
									MakefileData.ToMakefilePath (pair.Value.File.RelativeTargetPath));
					}
				}
				
				conf_vars.Append ('\n');
				
				StringBuilder vars = new StringBuilder ();
				foreach (KeyValuePair<string, StringBuilder> pair in deployDirs) {
					//PROGRAM_FILES= .. etc
					conf_vars.AppendFormat ("{0} = {1} \n\n", pair.Key, pair.Value.ToString ());
					//Build list of deploy dir variables
					vars.AppendFormat ("$({0}) ", pair.Key);
				}

				if (!generateAutotools) {
					installTarget.Insert (0, String.Format ("install-local:{0}\n", installDeps.ToString ()));
					installTarget.Append ("\tmake post-install-local-hook prefix=$(prefix)\n");

					uninstallTarget.Insert (0, String.Format ("uninstall-local:{0}\n", installDeps.ToString ()));
					uninstallTarget.Append ("\tmake post-uninstall-local-hook prefix=$(prefix)\n");
				}

				if (!generateAutotools && customCommands.Length > 0)
					customCommands.Insert (0, "# Targets for Custom commands\n");

				templateEngine.Variables["CONFIG_VARS"] = conf_vars.ToString ();
				templateEngine.Variables["DEPLOY_FILE_VARS"] = vars.ToString ();
				templateEngine.Variables["COPY_DEPLOY_FILES_VARS"] = deployFileCopyVars.ToString();
				templateEngine.Variables["COPY_DEPLOY_FILES_TARGETS"] = deployFileCopyTargets.ToString();
				templateEngine.Variables["ALL_TARGET"] = (ctx.TargetSolution.BaseDirectory == project.BaseDirectory) ? "all-local" : "all";
				templateEngine.Variables["INCLUDES"] = includes;

				templateEngine.Variables["FILES"] = files.ToString();
				templateEngine.Variables["RESOURCES"] = res_files.ToString();
				templateEngine.Variables["EXTRAS"] = extras.ToString();
				templateEngine.Variables["DATA_FILES"] = datafiles.ToString();
				templateEngine.Variables["CLEANFILES"] = vars.ToString ();

				if (!generateAutotools) {
					templateEngine.Variables["TEMPLATE_FILES_TARGETS"] = templateFilesTargets.ToString();
					templateEngine.Variables["INSTALL_TARGET"] = installTarget.ToString();
					templateEngine.Variables["UNINSTALL_TARGET"] = uninstallTarget.ToString();
					templateEngine.Variables["CUSTOM_COMMAND_TARGETS"] = customCommands.ToString();
				}

				// Create project specific makefile
				Stream stream = ctx.GetTemplateStream (
						generateAutotools ? "Makefile.am.project.template" : "Makefile.noauto.project.template");

				StreamReader reader = new StreamReader (stream);
				string txt = templateEngine.Process ( reader );
				reader.Close();

				makefile.Append ( txt );
				monitor.Step (1);
			}
			finally	{ monitor.EndTask (); }
			return makefile;
		}
Beispiel #3
0
        public Makefile Deploy(AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor)
        {
            generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile;

            monitor.BeginTask(GettextCatalog.GetString(
                                  "Creating {0} for Project {1}",
                                  generateAutotools ? "Makefile.am" : "Makefile", entry.Name), 1);

            Makefile makefile = new Makefile();

            try
            {
                if (!CanDeploy(entry, generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile))
                {
                    throw new Exception(GettextCatalog.GetString("Not a deployable project."));
                }

                Project               project        = entry as Project;
                TemplateEngine        templateEngine = new TemplateEngine();
                ISimpleAutotoolsSetup setup          = FindSetupForProject(project);

                // Handle files to be deployed
                deployDirs            = new Dictionary <string, StringBuilder> ();
                deployFileVars        = new Dictionary <string, string> ();
                builtFiles            = new List <string> ();
                deployFileCopyVars    = new StringBuilder();
                deployFileCopyTargets = new StringBuilder();

                //used only for simple makefile generation
                templateFilesTargets = null;
                installTarget        = null;
                installDeps          = null;
                installDirs          = null;
                uninstallTarget      = null;

                // handle configuration specific variables
                conf_vars = new StringBuilder();

                // grab all project files
                files     = new StringBuilder();
                res_files = new StringBuilder();
                extras    = new StringBuilder();
                datafiles = new StringBuilder();
                Set <string> extraFiles = new Set <string> ();

                string        includes = String.Empty;
                string        references, dllReferences;
                DotNetProject netProject = project as DotNetProject;
                ProcessProjectReferences(netProject, out references, out dllReferences, ctx);

                templateEngine.Variables["REFERENCES"]     = references;
                templateEngine.Variables["DLL_REFERENCES"] = dllReferences;
                templateEngine.Variables["WARNING"]        = "Warning: This is an automatically generated file, do not edit!";

                DotNetProject dotnetProject = entry as DotNetProject;
                if (dotnetProject != null)
                {
                    string resgen = "resgen";
                    if (System.Environment.Version.Major >= 2)
                    {
                        switch (dotnetProject.TargetFramework.ClrVersion)
                        {
                        case ClrVersion.Net_2_0: resgen = "resgen2"; break;

                        case ClrVersion.Net_1_1: resgen = "resgen1"; break;
                        }
                    }
                    templateEngine.Variables ["RESGEN"] = resgen;
                }

                string pfpath = null;
                foreach (ProjectFile projectFile in project.Files)
                {
                    pfpath = FileService.NormalizeRelativePath(projectFile.FilePath.ToRelative(project.BaseDirectory));
                    switch (projectFile.BuildAction)
                    {
                    case BuildAction.Compile:

                        if (projectFile.Subtype != Subtype.Code)
                        {
                            continue;
                        }
                        files.AppendFormat("\\\n\t{0} ", MakefileData.ToMakefilePath(pfpath));
                        break;

                    case BuildAction.Content:
                    case BuildAction.None:

                        extraFiles.Add(MakefileData.ToMakefilePath(pfpath));
                        break;

                    case BuildAction.EmbeddedResource:

                        if (!projectFile.FilePath.IsChildPathOf(ctx.BaseDirectory))
                        {
                            // file is not within directory hierarchy, copy it in
                            string rdir = Path.Combine(Path.GetDirectoryName(project.FileName), resourcedir);
                            if (!Directory.Exists(rdir))
                            {
                                Directory.CreateDirectory(rdir);
                            }
                            string newPath = Path.Combine(rdir, Path.GetFileName(projectFile.FilePath));
                            FileService.CopyFile(projectFile.FilePath, newPath);
                            pfpath = project.GetRelativeChildPath(newPath);
                            pfpath = FileService.NormalizeRelativePath(pfpath);
                        }
                        if (!String.IsNullOrEmpty(projectFile.ResourceId) && projectFile.ResourceId != Path.GetFileName(pfpath))
                        {
                            res_files.AppendFormat("\\\n\t{0},{1} ", MakefileData.ToMakefilePath(pfpath), MakefileData.EscapeString(projectFile.ResourceId));
                        }
                        else
                        {
                            res_files.AppendFormat("\\\n\t{0} ", MakefileData.ToMakefilePath(pfpath));
                        }

                        break;

                    case "FileCopy":

                        datafiles.AppendFormat("\\\n\t{0} ", MakefileData.ToMakefilePath(pfpath));
                        break;
                    }
                }

                if (!generateAutotools)
                {
                    templateFilesTargets = new StringBuilder();
                    installTarget        = new StringBuilder();
                    uninstallTarget      = new StringBuilder();
                    installDeps          = new StringBuilder();
                    installDirs          = new List <string> ();

                    customCommands = new StringBuilder();

                    string programFilesDir = ctx.DeployContext.GetDirectory(TargetDirectory.ProgramFiles);
                    //FIXME:temp
                    programFilesDir = TranslateDir(programFilesDir);
                    installDirs.Add(programFilesDir);
                    installTarget.Append("\tmake pre-install-local-hook prefix=$(prefix)\n");
                    installTarget.Append("\tmake install-satellite-assemblies prefix=$(prefix)\n");
                    installTarget.AppendFormat("\tmkdir -p '$(DESTDIR){0}'\n", programFilesDir);
                    installTarget.AppendFormat("\t$(call cp,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
                    installTarget.AppendFormat("\t$(call cp,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

                    //remove dir?
                    uninstallTarget.Append("\tmake pre-uninstall-local-hook prefix=$(prefix)\n");
                    uninstallTarget.Append("\tmake uninstall-satellite-assemblies prefix=$(prefix)\n");
                    uninstallTarget.AppendFormat("\t$(call rm,$(ASSEMBLY),$(DESTDIR){0})\n", programFilesDir);
                    uninstallTarget.AppendFormat("\t$(call rm,$(ASSEMBLY_MDB),$(DESTDIR){0})\n", programFilesDir);

                    installDeps.Append(" $(ASSEMBLY) $(ASSEMBLY_MDB)");

                    conf_vars.AppendFormat("srcdir=.\n");
                    conf_vars.AppendFormat("top_srcdir={0}\n\n",
                                           FileService.AbsoluteToRelativePath(project.BaseDirectory, ctx.TargetSolution.BaseDirectory));

                    conf_vars.AppendFormat("include $(top_srcdir)/config.make\n\n");

                    // Don't emit for top level project makefile(eg. pdn.make), as it would be
                    // included by top level solution makefile
                    if (ctx.TargetSolution.BaseDirectory != project.BaseDirectory)
                    {
                        string customhooks = Path.Combine(project.BaseDirectory, "custom-hooks.make");
                        bool   include     = File.Exists(customhooks);

                        includes  = "include $(top_srcdir)/Makefile.include\n";
                        includes += String.Format("{0}include $(srcdir)/custom-hooks.make\n\n", include ? "" : "#");
                        if (include)
                        {
                            makefile.SetVariable("EXTRA_DIST", "$(srcdir)/custom-hooks.make");
                        }
                    }
                }

                bool buildEnabled;
                List <ConfigSection> configSections = new List <ConfigSection> ();
                allDeployVars = new Dictionary <string, DeployFileData> ();

                foreach (SolutionConfiguration combineConfig in ctx.TargetSolution.Configurations)
                {
                    DotNetProjectConfiguration config = GetProjectConfig(combineConfig.Id, project, out buildEnabled) as DotNetProjectConfiguration;
                    if (config == null)
                    {
                        continue;
                    }

                    ConfigSection configSection = new ConfigSection(combineConfig.Id);

                    string assembly = MakefileData.GetUnixPath(project.GetRelativeChildPath(config.CompiledOutputName));

                    configSection.BuildVariablesBuilder.AppendFormat("ASSEMBLY_COMPILER_COMMAND = {0}\n",
                                                                     setup.GetCompilerCommand(project, config.Id));
                    configSection.BuildVariablesBuilder.AppendFormat("ASSEMBLY_COMPILER_FLAGS = {0}\n",
                                                                     setup.GetCompilerFlags(project, config.Id));

                    // add check for compiler command in configure.ac
                    ctx.AddCommandCheck(setup.GetCompilerCommand(project, config.Id));

                    configSection.BuildVariablesBuilder.AppendFormat("ASSEMBLY = {0}\n",
                                                                     AutotoolsContext.EscapeStringForAutomake(assembly));
                    configSection.BuildVariablesBuilder.AppendFormat("ASSEMBLY_MDB = {0}\n",
                                                                     config.DebugMode ? "$(ASSEMBLY).mdb" : String.Empty);

                    string target;
                    switch (config.CompileTarget)
                    {
                    case CompileTarget.Exe:
                        target = "exe";
                        break;

                    case CompileTarget.Library:
                        target = "library";
                        break;

                    case CompileTarget.WinExe:
                        target = "winexe";
                        break;

                    case CompileTarget.Module:
                        target = "module";
                        break;

                    default:
                        throw new Exception(GettextCatalog.GetString("Unknown target {0}", config.CompileTarget));
                    }
                    configSection.BuildVariablesBuilder.AppendFormat("COMPILE_TARGET = {0}\n", target);

                    // for project references, we need a ref to the dll for the current configuration
                    StringWriter projectReferences = new StringWriter();
                    string       pref = null;
                    foreach (ProjectReference reference in netProject.References)
                    {
                        if (reference.ReferenceType != ReferenceType.Project)
                        {
                            continue;
                        }
                        Project refp = GetProjectFromName(reference.Reference, ctx.TargetSolution);

                        if (!(refp is DotNetProject))
                        {
                            continue;
                        }

                        DotNetProjectConfiguration dnpc = GetProjectConfig(combineConfig.Id, refp, out buildEnabled) as DotNetProjectConfiguration;
                        if (dnpc == null)
                        {
                            throw new Exception(GettextCatalog.GetString
                                                    ("Could not add reference to project '{0}'", refp.Name));
                        }

                        projectReferences.WriteLine(" \\");
                        projectReferences.Write("\t");
                        pref = project.GetRelativeChildPath(dnpc.CompiledOutputName);

                        projectReferences.Write(MakefileData.ToMakefilePath(pref));
                    }
                    configSection.BuildVariablesBuilder.AppendFormat("PROJECT_REFERENCES = {0}\n", projectReferences.ToString());

                    string buildDir = project.GetRelativeChildPath(config.OutputDirectory);
                    configSection.BuildVariablesBuilder.AppendFormat("BUILD_DIR = {0}\n", MakefileData.ToMakefilePath(buildDir));

                    // Register files built by this configuration.
                    // Built files won't be distributed.
                    foreach (string bfile in builtFiles)
                    {
                        ctx.AddBuiltFile(Path.Combine(config.OutputDirectory, bfile));
                    }

                    DeployFileCollection deployFiles = DeployService.GetDeployFiles(
                        ctx.DeployContext, new SolutionItem[] { project }, config.Selector);

                    ProcessDeployFilesForConfig(deployFiles, project, configSection, ctx, config);
                    configSections.Add(configSection);

                    if (!generateAutotools)
                    {
                        EmitCustomCommandTargets(config.CustomCommands, project, customCommands, combineConfig.Id,
                                                 new CustomCommandType [] {
                            CustomCommandType.BeforeBuild,
                            CustomCommandType.AfterBuild,
                            CustomCommandType.BeforeClean,
                            CustomCommandType.AfterClean
                        }, monitor);
                    }
                    else
                    {
                        if (config.CustomCommands.Count > 0)
                        {
                            monitor.ReportWarning(GettextCatalog.GetString("Custom commands are not supported for autotools based makefiles. Ignoring."));
                        }
                    }

                    // Register files generated by the compiler
                    ctx.AddBuiltFile(project.GetOutputFileName(combineConfig.Selector));
                    if (config.DebugMode)
                    {
                        ctx.AddBuiltFile(project.GetOutputFileName(combineConfig.Selector) + ".mdb");
                    }

                    if (config.SignAssembly)
                    {
                        string spath = project.GetRelativeChildPath(config.AssemblyKeyFile);
                        spath = FileService.NormalizeRelativePath(spath);
                        extraFiles.Add(MakefileData.ToMakefilePath(spath));
                    }

                    if (buildEnabled && pkgs.Count > 0)
                    {
                        ctx.AddRequiredPackages(combineConfig.Id, pkgs);
                    }
                }


                foreach (string ef in extraFiles)
                {
                    extras.AppendFormat("\\\n\t{0} ", ef);
                }

                Dictionary <string, DeployFileData> commonDeployVars = new Dictionary <string, DeployFileData> (allDeployVars);
                foreach (ConfigSection configSection in configSections)
                {
                    List <string> toRemove = new List <string> ();
                    foreach (KeyValuePair <string, DeployFileData> pair in commonDeployVars)
                    {
                        if (!configSection.DeployFileVars.ContainsKey(pair.Key))
                        {
                            toRemove.Add(pair.Key);
                        }
                    }
                    foreach (string s in toRemove)
                    {
                        commonDeployVars.Remove(s);
                    }
                }

                //emit the config sections here.. to conf_vars
                foreach (ConfigSection configSection in configSections)
                {
                    conf_vars.AppendFormat(generateAutotools ? "if ENABLE_{0}\n" : "ifeq ($(CONFIG),{0})\n",
                                           ctx.EscapeAndUpperConfigName(configSection.Name));

                    conf_vars.Append(configSection.BuildVariablesBuilder.ToString());
                    conf_vars.Append("\n");

                    if (ctx.Switches != null)
                    {
                        foreach (Switch s in ctx.Switches)
                        {
                            conf_vars.AppendLine(string.Format(@"if ENABLE_{0}
ASSEMBLY_COMPILER_FLAGS += -define:{1}
endif", s.SwitchName.Replace('-', '_').ToUpperInvariant(), s.Define));
                        }
                    }

                    foreach (KeyValuePair <string, DeployFileData> pair in allDeployVars)
                    {
                        string targetDeployVar = pair.Key;
                        if (pair.Value.File.ContainsPathReferences)
                        {
                            //Template files are not handled per-config
                            continue;
                        }

                        if (configSection.DeployFileVars.ContainsKey(targetDeployVar))
                        {
                            //use the dfile from the config section
                            DeployFile dfile = configSection.DeployFileVars [targetDeployVar];
                            string     fname = MakefileData.ToMakefilePath(
                                FileService.AbsoluteToRelativePath(
                                    Path.GetFullPath(project.BaseDirectory),
                                    Path.GetFullPath(dfile.SourcePath)));

                            conf_vars.AppendFormat("{0}_SOURCE={1}\n", targetDeployVar, fname);

                            if (!commonDeployVars.ContainsKey(targetDeployVar))
                            {
                                //FOO_DLL=$(BUILD_DIR)/foo.dll
                                conf_vars.AppendFormat("{0}=$(BUILD_DIR)/{1}\n",
                                                       targetDeployVar,
                                                       MakefileData.ToMakefilePath(dfile.RelativeTargetPath));
                            }
                        }
                        else
                        {
                            // not common and not part of @configSection
                            conf_vars.AppendFormat("{0}=\n", pair.Key);
                        }
                    }

                    conf_vars.Append("\nendif\n\n");
                }

                conf_vars.AppendFormat("AL={0}\n", (dotnetProject.TargetFramework.ClrVersion == ClrVersion.Net_2_0) ? "al2" : "al");
                conf_vars.AppendFormat("SATELLITE_ASSEMBLY_NAME=$(notdir $(basename $(ASSEMBLY))).resources.dll\n");

                foreach (KeyValuePair <string, DeployFileData> pair in allDeployVars)
                {
                    HandleDeployFile(pair.Value, pair.Key, project, ctx);

                    if (commonDeployVars.ContainsKey(pair.Key))
                    {
                        //FOO_DLL=$(BUILD_DIR)/foo.dll
                        deployFileCopyVars.AppendFormat("{0} = $(BUILD_DIR)/{1}\n",
                                                        pair.Key,
                                                        MakefileData.ToMakefilePath(pair.Value.File.RelativeTargetPath));
                    }
                }

                conf_vars.Append('\n');

                StringBuilder vars = new StringBuilder();
                foreach (KeyValuePair <string, StringBuilder> pair in deployDirs)
                {
                    //PROGRAM_FILES= .. etc
                    conf_vars.AppendFormat("{0} = {1} \n\n", pair.Key, pair.Value.ToString());
                    //Build list of deploy dir variables
                    vars.AppendFormat("$({0}) ", pair.Key);
                }

                if (!generateAutotools)
                {
                    installTarget.Insert(0, String.Format("install-local:{0}\n", installDeps.ToString()));
                    installTarget.Append("\tmake post-install-local-hook prefix=$(prefix)\n");

                    uninstallTarget.Insert(0, String.Format("uninstall-local:{0}\n", installDeps.ToString()));
                    uninstallTarget.Append("\tmake post-uninstall-local-hook prefix=$(prefix)\n");
                }

                if (!generateAutotools && customCommands.Length > 0)
                {
                    customCommands.Insert(0, "# Targets for Custom commands\n");
                }

                templateEngine.Variables["CONFIG_VARS"]               = conf_vars.ToString();
                templateEngine.Variables["DEPLOY_FILE_VARS"]          = vars.ToString();
                templateEngine.Variables["COPY_DEPLOY_FILES_VARS"]    = deployFileCopyVars.ToString();
                templateEngine.Variables["COPY_DEPLOY_FILES_TARGETS"] = deployFileCopyTargets.ToString();
                templateEngine.Variables["ALL_TARGET"] = (ctx.TargetSolution.BaseDirectory == project.BaseDirectory) ? "all-local" : "all";
                templateEngine.Variables["INCLUDES"]   = includes;

                templateEngine.Variables["FILES"]      = files.ToString();
                templateEngine.Variables["RESOURCES"]  = res_files.ToString();
                templateEngine.Variables["EXTRAS"]     = extras.ToString();
                templateEngine.Variables["DATA_FILES"] = datafiles.ToString();
                templateEngine.Variables["CLEANFILES"] = vars.ToString();

                if (!generateAutotools)
                {
                    templateEngine.Variables["TEMPLATE_FILES_TARGETS"] = templateFilesTargets.ToString();
                    templateEngine.Variables["INSTALL_TARGET"]         = installTarget.ToString();
                    templateEngine.Variables["UNINSTALL_TARGET"]       = uninstallTarget.ToString();
                    templateEngine.Variables["CUSTOM_COMMAND_TARGETS"] = customCommands.ToString();
                }

                // Create project specific makefile
                Stream stream = ctx.GetTemplateStream(
                    generateAutotools ? "Makefile.am.project.template" : "Makefile.noauto.project.template");

                StreamReader reader = new StreamReader(stream);
                string       txt    = templateEngine.Process(reader);
                reader.Close();

                makefile.Append(txt);
                monitor.Step(1);
            }
            finally { monitor.EndTask(); }
            return(makefile);
        }
		// Populates configSection.DeployFileVars with unique DeployFiles for a particular config
		void ProcessDeployFilesForConfig (DeployFileCollection deployFiles, Project project, ConfigSection configSection, AutotoolsContext ctx, DotNetProjectConfiguration config)
		{
			//@deployFiles can have duplicates
			Dictionary<string, DeployFile> uniqueDeployFiles = new Dictionary<string, DeployFile> ();
			foreach (DeployFile dfile in deployFiles) {
				if (dfile.SourcePath == project.GetOutputFileName (configSection.Selector))
					continue;

				// DeployFileCollection can have duplicates, ignore them
				string key = dfile.RelativeTargetPath;
				if (!dfile.ContainsPathReferences)
					key += dfile.SourcePath;
				if (uniqueDeployFiles.ContainsKey (key))
					continue;
				uniqueDeployFiles [key] = dfile;

				string targetDeployVar = GetDeployVar (deployFileVars, dfile.RelativeTargetPath);
				configSection.DeployFileVars [targetDeployVar] = dfile;
				DeployFileData data = new DeployFileData ();
				data.File = dfile;
				data.Configuration = config;
				allDeployVars [targetDeployVar] = data;
			}
		}