public Makefile Deploy(AutotoolsContext ctx, SolutionItem entry, IProgressMonitor monitor) { generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile; monitor.BeginTask(GettextCatalog.GetString( "Creating {0} for Solution {1}", generateAutotools ? "Makefile.am" : "Makefile", entry.Name), 1); Makefile solutionMakefile = new Makefile(); StringBuilder solutionTop = new StringBuilder(); try { SolutionFolder solutionFolder = (SolutionFolder)entry; string targetDirectory = solutionFolder.BaseDirectory; StringBuilder subdirs = new StringBuilder(); subdirs.Append("#Warning: This is an automatically generated file, do not edit!\n"); if (!generateAutotools) { solutionTop.AppendFormat("top_srcdir={0}\n", FileService.AbsoluteToRelativePath( entry.BaseDirectory, ctx.TargetSolution.BaseDirectory)); solutionTop.Append("include $(top_srcdir)/config.make\n"); solutionTop.Append("include $(top_srcdir)/Makefile.include\n"); solutionTop.Append("include $(top_srcdir)/rules.make\n\n"); solutionTop.Append("#include $(top_srcdir)/custom-hooks.make\n\n"); } ArrayList children = new ArrayList(); foreach (SolutionConfiguration config in solutionFolder.ParentSolution.Configurations) { if (!ctx.IsSupportedConfiguration(config.Id)) { continue; } if (generateAutotools) { subdirs.AppendFormat("if {0}\n", "ENABLE_" + ctx.EscapeAndUpperConfigName(config.Id)); } else { subdirs.AppendFormat("ifeq ($(CONFIG),{0})\n", ctx.EscapeAndUpperConfigName(config.Id)); } subdirs.Append(" SUBDIRS = "); foreach (SolutionItem ce in CalculateSubDirOrder(ctx, solutionFolder, config)) { string baseDirectory; if (!(ce is SolutionEntityItem) && !(ce is SolutionFolder)) { continue; } // Ignore projects which can't be deployed IMakefileHandler handler = AutotoolsContext.GetMakefileHandler(ce, ctx.MakefileType); if (handler == null) { continue; } baseDirectory = ce.BaseDirectory; if (solutionFolder.BaseDirectory == baseDirectory) { subdirs.Append(" . "); } else { if (!baseDirectory.StartsWith(solutionFolder.BaseDirectory)) { throw new Exception(GettextCatalog.GetString( "Child projects must be in sub-directories of their parent")); } // add the subdirectory to the list string path = FileService.AbsoluteToRelativePath(targetDirectory, baseDirectory); if (path.StartsWith("." + Path.DirectorySeparatorChar)) { path = path.Substring(2); } AutotoolsContext.CheckSpaces(path); subdirs.Append(" "); subdirs.Append(AutotoolsContext.EscapeStringForAutomake(path)); } if (!children.Contains(ce)) { children.Add(ce); } } subdirs.Append("\nendif\n"); } solutionTop.Append(subdirs.ToString()); string includedProject = null; // deploy recursively foreach (SolutionItem ce in children) { IMakefileHandler handler = AutotoolsContext.GetMakefileHandler(ce, ctx.MakefileType); Makefile makefile; string outpath; if (handler != null && handler.CanDeploy(ce, ctx.MakefileType)) { ctx.RegisterBuiltProject(ce); makefile = handler.Deploy(ctx, ce, monitor); if (targetDirectory == ce.BaseDirectory) { if (includedProject != null) { throw new Exception(GettextCatalog.GetString( "More than 1 project in the same directory as the top-level solution is not supported.")); } // project is in the solution directory string projectMakefileName = ce.Name + ".make"; includedProject = String.Format("include {0}", projectMakefileName); outpath = Path.Combine(targetDirectory, projectMakefileName); ctx.AddGeneratedFile(outpath); if (!generateAutotools) { solutionMakefile.SetVariable("EXTRA_DIST", projectMakefileName); } } else { makefile.AppendToVariable("EXTRA_DIST", generateAutotools ? String.Empty : "Makefile"); outpath = Path.Combine(ce.BaseDirectory, "Makefile"); if (generateAutotools) { ctx.AddAutoconfFile(outpath); outpath = outpath + ".am"; } else { makefile.Append("install: install-local\nuninstall: uninstall-local\nclean: clean-local\n"); if (ce is SolutionFolder) { //non TargetCombine makefile.Append("dist-local: dist-local-recursive\n"); } else { makefile.Append("include $(top_srcdir)/rules.make\n"); } } ctx.AddGeneratedFile(outpath); } StreamWriter writer = new StreamWriter(outpath); makefile.Write(writer); writer.Close(); } else { monitor.Log.WriteLine("Project '{0}' skipped.", ce.Name); } } if (includedProject != null) { solutionTop.Append(GettextCatalog.GetString("\n# Include project specific makefile\n")); solutionTop.Append(includedProject); } if (generateAutotools) { solutionMakefile.Append(solutionTop.ToString()); } else { TemplateEngine templateEngine = new TemplateEngine(); templateEngine.Variables ["MAKEFILE_SOLUTION_TOP"] = solutionTop.ToString(); Stream stream = ctx.GetTemplateStream("Makefile.solution.template"); StreamReader reader = new StreamReader(stream); StringWriter sw = new StringWriter(); templateEngine.Process(reader, sw); reader.Close(); solutionMakefile.Append(sw.ToString()); if (solutionFolder.IsRoot) { // Emit dist and distcheck targets only for TargetCombine reader = new StreamReader(Path.Combine(ctx.TemplateDir, "make-dist.targets")); solutionMakefile.Append(reader.ReadToEnd()); reader.Close(); } } monitor.Step(1); } finally { monitor.EndTask(); } return(solutionMakefile); }
public Makefile Deploy (AutotoolsContext ctx, SolutionFolderItem entry, ProgressMonitor monitor) { generateAutotools = ctx.MakefileType == MakefileType.AutotoolsMakefile; monitor.BeginTask ( GettextCatalog.GetString ( "Creating {0} for Solution {1}", generateAutotools ? "Makefile.am" : "Makefile", entry.Name), 1 ); Makefile solutionMakefile = new Makefile (); StringBuilder solutionTop = new StringBuilder (); try { SolutionFolder solutionFolder = (SolutionFolder) entry; string targetDirectory = solutionFolder.BaseDirectory; StringBuilder subdirs = new StringBuilder(); subdirs.Append ("#Warning: This is an automatically generated file, do not edit!\n"); if (!generateAutotools) { solutionTop.AppendFormat ("top_srcdir={0}\n", FileService.AbsoluteToRelativePath ( entry.BaseDirectory, ctx.TargetSolution.BaseDirectory)); solutionTop.Append ("include $(top_srcdir)/config.make\n"); solutionTop.Append ("include $(top_srcdir)/Makefile.include\n"); solutionTop.Append ("include $(top_srcdir)/rules.make\n\n"); solutionTop.Append ("#include $(top_srcdir)/custom-hooks.make\n\n"); } ArrayList children = new ArrayList (); foreach ( SolutionConfiguration config in solutionFolder.ParentSolution.Configurations ) { if ( !ctx.IsSupportedConfiguration ( config.Id ) ) continue; if (generateAutotools) subdirs.AppendFormat ( "if {0}\n", "ENABLE_" + ctx.EscapeAndUpperConfigName (config.Id)); else subdirs.AppendFormat ( "ifeq ($(CONFIG),{0})\n", ctx.EscapeAndUpperConfigName (config.Id)); subdirs.Append (" SUBDIRS = "); foreach (SolutionFolderItem ce in CalculateSubDirOrder (ctx, solutionFolder, config)) { string baseDirectory; if (!(ce is SolutionItem) && !(ce is SolutionFolder)) continue; // Ignore projects which can't be deployed IMakefileHandler handler = AutotoolsContext.GetMakefileHandler (ce, ctx.MakefileType); if (handler == null) continue; baseDirectory = ce.BaseDirectory; if (solutionFolder.BaseDirectory == baseDirectory) { subdirs.Append (" . "); } else { if (!baseDirectory.StartsWith (solutionFolder.BaseDirectory) ) throw new Exception ( GettextCatalog.GetString ( "Child projects must be in sub-directories of their parent") ); // add the subdirectory to the list string path = FileService.AbsoluteToRelativePath (targetDirectory, baseDirectory); if (path.StartsWith ("." + Path.DirectorySeparatorChar) ) path = path.Substring (2); AutotoolsContext.CheckSpaces (path); subdirs.Append (" "); subdirs.Append ( AutotoolsContext.EscapeStringForAutomake (path) ); } if (!children.Contains (ce)) children.Add ( ce ); } subdirs.Append ( "\nendif\n" ); } solutionTop.Append ( subdirs.ToString () ); string includedProject = null; // deploy recursively foreach (SolutionFolderItem ce in children) { IMakefileHandler handler = AutotoolsContext.GetMakefileHandler ( ce, ctx.MakefileType ); Makefile makefile; string outpath; if ( handler != null && handler.CanDeploy ( ce, ctx.MakefileType ) ) { ctx.RegisterBuiltProject (ce); makefile = handler.Deploy ( ctx, ce, monitor ); if (targetDirectory == ce.BaseDirectory) { if (includedProject != null) throw new Exception ( GettextCatalog.GetString ( "More than 1 project in the same directory as the top-level solution is not supported.")); // project is in the solution directory string projectMakefileName = ce.Name + ".make"; includedProject = String.Format ("include {0}", projectMakefileName); outpath = Path.Combine (targetDirectory, projectMakefileName); ctx.AddGeneratedFile (outpath); if (!generateAutotools) solutionMakefile.SetVariable ("EXTRA_DIST", projectMakefileName); } else { makefile.AppendToVariable ("EXTRA_DIST", generateAutotools ? String.Empty : "Makefile"); outpath = Path.Combine (ce.BaseDirectory, "Makefile"); if (generateAutotools) { ctx.AddAutoconfFile (outpath); outpath = outpath + ".am"; } else { makefile.Append ("install: install-local\nuninstall: uninstall-local\nclean: clean-local\n"); if (ce is SolutionFolder) //non TargetCombine makefile.Append ("dist-local: dist-local-recursive\n"); else makefile.Append ("include $(top_srcdir)/rules.make\n"); } ctx.AddGeneratedFile (outpath); } StreamWriter writer = new StreamWriter (outpath); makefile.Write ( writer ); writer.Close (); } else { monitor.Log .WriteLine("Project '{0}' skipped.", ce.Name); } } if (includedProject != null) { solutionTop.Append (GettextCatalog.GetString ("\n# Include project specific makefile\n")); solutionTop.Append (includedProject); } if (generateAutotools) { solutionMakefile.Append (solutionTop.ToString ()); } else { TemplateEngine templateEngine = new TemplateEngine (); templateEngine.Variables ["MAKEFILE_SOLUTION_TOP"] = solutionTop.ToString (); Stream stream = ctx.GetTemplateStream ("Makefile.solution.template"); StreamReader reader = new StreamReader (stream); StringWriter sw = new StringWriter (); templateEngine.Process (reader, sw); reader.Close (); solutionMakefile.Append (sw.ToString ()); if (solutionFolder.IsRoot) { // Emit dist and distcheck targets only for TargetCombine reader = new StreamReader (Path.Combine (ctx.TemplateDir, "make-dist.targets")); solutionMakefile.Append (reader.ReadToEnd ()); reader.Close (); } } monitor.Step (1); } finally { monitor.EndTask (); } return solutionMakefile; }
// Handle unique deploy files, emits non-perconfig stuff, like targets for deploy files, // un/install commands void HandleDeployFile(DeployFileData data, string targetDeployVar, Project project, AutotoolsContext ctx) { DeployFile dfile = data.File; string dependencyDeployFile = null; //Dependency for the deployfile target if (dfile.ContainsPathReferences) { // Template file, copy to .in file string full_fname = Path.Combine(project.BaseDirectory, Path.GetFileName(dfile.RelativeTargetPath)); string fname = full_fname; string infname = fname + ".in"; if (File.Exists(infname) && project.IsFileInProject(infname)) { string datadir = Path.Combine(project.BaseDirectory, "data"); if (!Directory.Exists(datadir)) { Directory.CreateDirectory(datadir); } infname = Path.Combine(datadir, Path.GetFileName(dfile.RelativeTargetPath) + ".in"); } //Absolute path required File.Copy(dfile.SourcePath, infname, true); //Path relative to TargetCombine fname = FileService.NormalizeRelativePath( FileService.AbsoluteToRelativePath(ctx.TargetSolution.BaseDirectory, full_fname)); infname = fname + ".in"; ctx.AddAutoconfFile(MakefileData.ToMakefilePath(fname)); ctx.AddGeneratedFile(full_fname + ".in"); //Path relative to project fname = FileService.NormalizeRelativePath( FileService.AbsoluteToRelativePath(project.BaseDirectory, full_fname)); infname = fname + ".in"; extras.AppendFormat("\\\n\t{0} ", MakefileData.ToMakefilePath(infname)); //dependencyDeployFile here should be filename relative to the project dependencyDeployFile = fname; } else { dependencyDeployFile = String.Format("$({0}_SOURCE)", targetDeployVar); } builtFiles.Add(Path.GetFileName(dfile.RelativeTargetPath)); if (dfile.ContainsPathReferences) { deployFileCopyTargets.AppendFormat("$(eval $(call emit-deploy-wrapper,{0},{1}{2}))\n", targetDeployVar, MakefileData.ToMakefilePath(dependencyDeployFile), (dfile.FileAttributes & DeployFileAttributes.Executable) != 0 ? ",x" : String.Empty); } else { // The emit-deploy-target macro copies the deployable file to the output directory. // This is not needed if the file is already there (e.g. for an .mdb file) if (Path.GetFullPath(dfile.SourcePath) != Path.GetFullPath(Path.Combine(data.Configuration.OutputDirectory, dfile.RelativeTargetPath))) { deployFileCopyTargets.AppendFormat("$(eval $(call emit-deploy-target,{0}))\n", targetDeployVar); } } switch (dfile.TargetDirectoryID) { case TargetDirectory.Gac: // TODO break; default: string var; if (dfile.TargetDirectoryID != TargetDirectory.Binaries) { string ddir = FileService.NormalizeRelativePath(dfile.RelativeTargetPath.ParentDirectory.ToString().Trim('/', ' ')); if (ddir.Length > 0) { ddir = "/" + ddir; } var = ctx.GetDeployDirectoryVar(dfile.TargetDirectoryID + ddir); } else { var = "BINARIES"; } StringBuilder sb; if (!deployDirs.TryGetValue(var, out sb)) { sb = new StringBuilder(); deployDirs [var] = sb; } sb.AppendFormat("\\\n\t$({0}) ", targetDeployVar); break; } if (!generateAutotools) { string installDir = Path.GetDirectoryName(ctx.DeployContext.GetResolvedPath(dfile.TargetDirectoryID, dfile.RelativeTargetPath)); //FIXME: temp installDir = TranslateDir(installDir); if (!installDirs.Contains(installDir)) { installTarget.AppendFormat("\tmkdir -p '$(DESTDIR){0}'\n", installDir); installDirs.Add(installDir); } installTarget.AppendFormat("\t$(call cp,$({0}),$(DESTDIR){1})\n", targetDeployVar, installDir); uninstallTarget.AppendFormat("\t$(call rm,$({1}),$(DESTDIR){0})\n", installDir, targetDeployVar); } }
public bool GenerateFiles(DeployContext ctx, Solution solution, string defaultConf, IProgressMonitor monitor) { string filesString = generateAutotools ? "Autotools files" : "Makefiles"; monitor.BeginTask(GettextCatalog.GetString("Generating {0} for Solution {1}", filesString, solution.Name), 1); try { solution_dir = Path.GetDirectoryName(solution.FileName); string[] configs = new string [solution.Configurations.Count]; for (int ii = 0; ii < configs.Length; ii++) { configs [ii] = solution.Configurations[ii].Id; } MakefileType mt = generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile; context = new AutotoolsContext(ctx, solution_dir, configs, mt); context.TargetSolution = solution; context.Switches = switchs; IMakefileHandler handler = AutotoolsContext.GetMakefileHandler(solution.RootFolder, mt); if (handler == null) { throw new Exception(GettextCatalog.GetString("MonoDevelop does not currently support generating {0} for one (or more) child projects.", filesString)); } solution_name = solution.Name; solution_version = AutotoolsContext.EscapeStringForAutoconf(solution.Version, true); if (string.IsNullOrEmpty(solution_version)) { solution_version = "0.1"; } Makefile makefile = handler.Deploy(context, solution.RootFolder, monitor); string path = Path.Combine(solution_dir, "Makefile"); if (generateAutotools) { context.AddAutoconfFile(path); CreateAutoGenDotSH(context, monitor); CreateConfigureDotAC(solution, defaultConf, monitor, context); CreateMacros(); } else { CreateConfigureScript(solution, defaultConf, context, monitor); monitor.Log.WriteLine(GettextCatalog.GetString("Creating rules.make")); string rules_make_path = Path.Combine(solution_dir, "rules.make"); File.Copy(Path.Combine(context.TemplateDir, "rules.make"), rules_make_path, true); context.AddGeneratedFile(rules_make_path); } CreateMakefileInclude(context, monitor); AddTopLevelMakefileVars(makefile, monitor); if (generateAutotools) { path = path + ".am"; } StreamWriter writer = new StreamWriter(path); makefile.Write(writer); writer.Close(); context.AddGeneratedFile(path); monitor.ReportSuccess(GettextCatalog.GetString("{0} were successfully generated.", filesString)); monitor.Step(1); } catch (Exception e) { monitor.ReportError(GettextCatalog.GetString("{0} could not be generated: ", filesString), e); LoggingService.LogError(GettextCatalog.GetString("{0} could not be generated: ", filesString), e); DeleteGeneratedFiles(context); return(false); } finally { monitor.EndTask(); } return(true); }
public bool GenerateFiles (DeployContext ctx, Solution solution, string defaultConf, IProgressMonitor monitor ) { string filesString = generateAutotools ? "Autotools files" : "Makefiles"; monitor.BeginTask ( GettextCatalog.GetString ("Generating {0} for Solution {1}", filesString, solution.Name), 1 ); try { solution_dir = Path.GetDirectoryName(solution.FileName); string[] configs = new string [ solution.Configurations.Count ]; for (int ii=0; ii < configs.Length; ii++ ) configs [ii] = solution.Configurations[ii].Id; MakefileType mt = generateAutotools ? MakefileType.AutotoolsMakefile : MakefileType.SimpleMakefile; context = new AutotoolsContext ( ctx, solution_dir, configs, mt ); context.TargetSolution = solution; context.Switches = switchs; IMakefileHandler handler = AutotoolsContext.GetMakefileHandler (solution.RootFolder, mt); if (handler == null) throw new Exception (string.Format ( "{0} does not currently support generating {1} for one (or more) child projects.", filesString, BrandingService.ApplicationName )); solution_name = solution.Name; solution_version = AutotoolsContext.EscapeStringForAutoconf (solution.Version, true); if (string.IsNullOrEmpty (solution_version)) solution_version = "0.1"; Makefile makefile = handler.Deploy ( context, solution.RootFolder, monitor ); string path = Path.Combine (solution_dir, "Makefile"); if (generateAutotools) { context.AddAutoconfFile (path); CreateAutoGenDotSH (context, monitor); CreateConfigureDotAC (solution, defaultConf, monitor, context); CreateMacros (); } else { CreateConfigureScript (solution, defaultConf, context, monitor); monitor.Log.WriteLine ( GettextCatalog.GetString ("Creating rules.make")); string rules_make_path = Path.Combine (solution_dir, "rules.make"); File.Copy (Path.Combine (context.TemplateDir, "rules.make"), rules_make_path, true); context.AddGeneratedFile (rules_make_path); } CreateMakefileInclude ( context, monitor ); AddTopLevelMakefileVars ( makefile, monitor ); if (generateAutotools) path = path + ".am"; StreamWriter writer = new StreamWriter (path); makefile.Write ( writer ); writer.Close (); context.AddGeneratedFile (path); monitor.ReportSuccess ( GettextCatalog.GetString ("{0} were successfully generated.", filesString ) ); monitor.Step (1); } catch ( Exception e ) { monitor.ReportError ( GettextCatalog.GetString ("{0} could not be generated: ", filesString ), e ); LoggingService.LogError (GettextCatalog.GetString ("{0} could not be generated: ", filesString ), e); DeleteGeneratedFiles ( context ); return false; } finally { monitor.EndTask (); } return true; }
// Handle unique deploy files, emits non-perconfig stuff, like targets for deploy files, // un/install commands void HandleDeployFile (DeployFileData data, string targetDeployVar, Project project, AutotoolsContext ctx) { DeployFile dfile = data.File; string dependencyDeployFile = null; //Dependency for the deployfile target if (dfile.ContainsPathReferences) { // Template file, copy to .in file string full_fname = Path.Combine (project.BaseDirectory, Path.GetFileName (dfile.RelativeTargetPath)); string fname = full_fname; string infname = fname + ".in"; if (File.Exists (infname) && project.IsFileInProject (infname)) { string datadir = Path.Combine (project.BaseDirectory, "data"); if (!Directory.Exists (datadir)) Directory.CreateDirectory (datadir); infname = Path.Combine (datadir, Path.GetFileName (dfile.RelativeTargetPath) + ".in"); } //Absolute path required File.Copy (dfile.SourcePath, infname, true); //Path relative to TargetCombine fname = FileService.NormalizeRelativePath ( FileService.AbsoluteToRelativePath (ctx.TargetSolution.BaseDirectory, full_fname)); infname = fname + ".in"; ctx.AddAutoconfFile (MakefileData.ToMakefilePath (fname)); ctx.AddGeneratedFile (full_fname + ".in"); //Path relative to project fname = FileService.NormalizeRelativePath ( FileService.AbsoluteToRelativePath (project.BaseDirectory, full_fname)); infname = fname + ".in"; extras.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (infname)); //dependencyDeployFile here should be filename relative to the project dependencyDeployFile = fname; } else { dependencyDeployFile = String.Format ("$({0}_SOURCE)", targetDeployVar); } builtFiles.Add (Path.GetFileName (dfile.RelativeTargetPath)); if (dfile.ContainsPathReferences) deployFileCopyTargets.AppendFormat ("$(eval $(call emit-deploy-wrapper,{0},{1}{2}))\n", targetDeployVar, MakefileData.ToMakefilePath (dependencyDeployFile), (dfile.FileAttributes & DeployFileAttributes.Executable) != 0 ? ",x" : String.Empty); else { // The emit-deploy-target macro copies the deployable file to the output directory. // This is not needed if the file is already there (e.g. for an .mdb file) if (Path.GetFullPath (dfile.SourcePath) != Path.GetFullPath (Path.Combine (data.Configuration.OutputDirectory, dfile.RelativeTargetPath))) deployFileCopyTargets.AppendFormat ("$(eval $(call emit-deploy-target,{0}))\n", targetDeployVar); } switch (dfile.TargetDirectoryID) { case TargetDirectory.Gac: // TODO break; default: string var; if (dfile.TargetDirectoryID != TargetDirectory.Binaries) { string ddir = FileService.NormalizeRelativePath (dfile.RelativeTargetPath.ParentDirectory.ToString().Trim ('/',' ')); if (ddir.Length > 0) ddir = "/" + ddir; var = ctx.GetDeployDirectoryVar (dfile.TargetDirectoryID + ddir); } else var = "BINARIES"; StringBuilder sb; if (!deployDirs.TryGetValue (var, out sb)) { sb = new StringBuilder (); deployDirs [var] = sb; } sb.AppendFormat ("\\\n\t$({0}) ", targetDeployVar); break; } if (!generateAutotools) { string installDir = Path.GetDirectoryName (ctx.DeployContext.GetResolvedPath (dfile.TargetDirectoryID, dfile.RelativeTargetPath)); //FIXME: temp installDir = TranslateDir (installDir); if (!installDirs.Contains (installDir)) { installTarget.AppendFormat ("\tmkdir -p '$(DESTDIR){0}'\n", installDir); installDirs.Add (installDir); } installTarget.AppendFormat ("\t$(call cp,$({0}),$(DESTDIR){1})\n", targetDeployVar, installDir); uninstallTarget.AppendFormat ("\t$(call rm,$({1}),$(DESTDIR){0})\n", installDir, targetDeployVar); } }