private static void GenerateNative(IProgressMonitor monitor, BuildResult result, MonobjcProject project, ConfigurationSelector configuration, BundleMaker maker) { // Create a directory for generation String tempDir = Path.Combine(project.GetOutputFileName(configuration).ParentDirectory, ".native"); Directory.CreateDirectory(tempDir); // Build a list of all folders to visit when collecting managed references String mainAssembly = project.GetOutputFileName(configuration); String configurationDir = Path.GetDirectoryName(mainAssembly); List<String> searchDirs = new List<String>(); searchDirs.Add(configurationDir); // For each reference, add its base dir foreach (ProjectReference reference in project.References) { String[] files = reference.GetReferencedFileNames(configuration); foreach (string file in files) { String dir = Path.GetDirectoryName(file); searchDirs.Add(dir); } } // Remove redundant entries searchDirs = searchDirs.Distinct().ToList(); // Collect all the assemblies monitor.BeginTask(GettextCatalog.GetString("Collecting assemblies..."), 0); ManagedReferenceCollector collector = new ManagedReferenceCollector(); collector.Logger = new BuildLogger(monitor, result); collector.SearchDirectories = searchDirs; monitor.EndTask(); // Collect the main assembly references List<String> assemblies = new List<String>(); assemblies.AddRange(collector.Collect(mainAssembly)); // Remove redundant entries assemblies = assemblies.Distinct().ToList(); // Generate the embedded executable monitor.BeginTask(GettextCatalog.GetString("Generating native code..."), 0); NativeCodeGenerator codeGenerator = new NativeCodeGenerator(); codeGenerator.Logger = new BuildLogger(monitor, result); codeGenerator.Assemblies = assemblies; codeGenerator.DeveloperToolsFolder = DeveloperToolsDesktopApplication.DeveloperToolsFolder; codeGenerator.TargetOSVersion = project.TargetOSVersion; codeGenerator.TargetArchitecture = project.TargetOSArch; // We embed the machine.config file; it depends on the target framework int version = (int) project.TargetFramework.ClrVersion; switch (version) { case 2: // ClrVersion.Net_2_0: codeGenerator.MachineConfiguration = "/Library/Frameworks/Mono.framework/Home/etc/mono/2.0/machine.config"; break; case 4: // ClrVersion.Net_4_0: codeGenerator.MachineConfiguration = "/Library/Frameworks/Mono.framework/Home/etc/mono/4.0/machine.config"; break; case 5: // ClrVersion.Net_4_5: codeGenerator.MachineConfiguration = "/Library/Frameworks/Mono.framework/Home/etc/mono/4.5/machine.config"; break; } // Launch the generation String executableFile = codeGenerator.Generate(tempDir); String libraryFile = Path.Combine(tempDir, "libmonobjc.dylib"); monitor.EndTask(); // Copy the native parts into the bundle monitor.BeginTask(GettextCatalog.GetString("Copying native code..."), 0); maker.CopyTo(executableFile, maker.MacOSDirectory); maker.CopyTo(libraryFile, maker.MacOSDirectory); monitor.EndTask(); // Change the paths executableFile = maker.Combine(maker.MacOSDirectory, executableFile); libraryFile = maker.Combine(maker.MacOSDirectory, libraryFile); // Relocate the libraries monitor.BeginTask(GettextCatalog.GetString("Relocating native code..."), 0); NativeCodeRelocator relocator = new NativeCodeRelocator(); relocator.Logger = new BuildLogger(monitor, result); relocator.DependencyPattern = new List<string> {"Mono.framework"}; relocator.Relocate(executableFile, maker.MacOSDirectory); relocator.Relocate(libraryFile, maker.MacOSDirectory); monitor.EndTask(); }
/// <summary> /// Executes the task. /// </summary> public override bool Execute() { if (this.SearchDirectories == null) { this.SearchDirectories = new ITaskItem[0]; } if (this.IncludedAssemblies == null) { this.IncludedAssemblies = new ITaskItem[0]; } if (this.ExcludedAssemblies == null) { this.ExcludedAssemblies = new ITaskItem[0]; } if (this.IncludedLibraries == null) { this.IncludedLibraries = new ITaskItem[0]; } if (this.MachineConfiguration == null) { this.MachineConfiguration = new TaskItem("/Library/Frameworks/Mono.framework/Home/etc/mono/4.0/machine.config"); } // HACK: We need to put a search directory in order to properly lookup assemblies with no explicit version List<ITaskItem> directories = this.SearchDirectories.ToList(); directories.Insert(0, new TaskItem(FileProvider.GetPath(this.targetOSVersion))); this.SearchDirectories = directories.ToArray(); // Set the working directory for the build String workingDir; if (this.WorkingDirectory == null) { workingDir = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); File.Delete(workingDir); this.WorkingDirectory = new TaskItem(workingDir); } workingDir = this.WorkingDirectory.ItemSpec; Directory.CreateDirectory(workingDir); // Set the output directory for the build String outputDir = this.ToDirectory.ItemSpec; Directory.CreateDirectory(outputDir); // Collect all the assemblies List<string> assemblies = this.GetAssemblies(); // Generate the embedded executable NativeCodeGenerator codeGenerator = new NativeCodeGenerator(); codeGenerator.Logger = new ExecutionLogger(this); codeGenerator.Assemblies = assemblies; codeGenerator.MachineConfiguration = this.MachineConfiguration.ItemSpec; codeGenerator.TargetOSVersion = this.targetOSVersion; codeGenerator.TargetArchitecture = this.targetArchitecture; codeGenerator.Compress = this.Compress; codeGenerator.UseSGEN = this.UseSGEN; codeGenerator.UseReceigen = this.UseReceigen; codeGenerator.NativeCompiler = this.NativeCompiler; codeGenerator.NativeCFLAGS = this.NativeCFLAGS; codeGenerator.NativeLDFLAGS = this.NativeLDFLAGS; String executableFile = codeGenerator.Generate(workingDir); // TODO: Use sgen if specified String libraryFile = Path.Combine(workingDir, "libmonobjc.dylib"); // Relocate the libraries NativeCodeRelocator relocator = new NativeCodeRelocator(); relocator.Logger = new ExecutionLogger(this); relocator.DependencyPattern = new List<string> {"Mono.framework"}; relocator.Relocate(executableFile, outputDir); relocator.Relocate(libraryFile, outputDir); // Copy the result files File.Copy(executableFile, Path.Combine(outputDir, Path.GetFileName(executableFile)), true); File.Copy(libraryFile, Path.Combine(outputDir, Path.GetFileName(libraryFile)), true); return true; }
/// <summary> /// Executes the task. /// </summary> protected override void ExecuteTask() { // Transform fileset into dir list if (this.SearchDirectories.Any(f => f.BaseDirectory == null)) { throw new BuildException("Missing 'basedir' attribute on <search-in/> sub-task"); } // Check included assemblies if (this.IncludedAssemblies.Any(f => f.File == null)) { throw new BuildException("Missing 'file' attribute on <include-assembly/> sub-task"); } // Check excluded assemblies if (this.ExcludedAssemblies.Any(f => f.File == null)) { throw new BuildException("Missing 'file' attribute on <exclude-assembly/> sub-task"); } // Check additionnal libraries if (this.IncludedLibraries.Any(f => f.File == null)) { throw new BuildException("Missing 'file' attribute on <include-library/> sub-task"); } // Set the output directory for the build String directory = this.ToDirectory.ToString(); Directory.CreateDirectory(directory); // Collect all the assemblies List<string> assemblies = this.GetAssemblies(); // Generate the embedded executable NativeCodeGenerator codeGenerator = new NativeCodeGenerator(); codeGenerator.Logger = new ExecutionLogger(this); codeGenerator.Assemblies = assemblies; codeGenerator.MachineConfiguration = this.MachineConfiguration; codeGenerator.TargetOSVersion = this.TargetOSVersion; codeGenerator.TargetArchitecture = this.TargetArchitecture; String executableFile = codeGenerator.Generate(directory); String libraryFile = Path.Combine(directory, "libmonobjc.dylib"); // Relocate the libraries NativeCodeRelocator relocator = new NativeCodeRelocator(); relocator.Logger = new ExecutionLogger(this); relocator.DependencyPattern = new List<string> {"Mono.framework"}; relocator.Relocate(executableFile, directory); relocator.Relocate(libraryFile, directory); }