public Generate ( String directory ) : String | ||
directory | String | The directory. |
return | String |
public String Generate(String directory)
{
NativeContext nativeContext = new NativeContext(this.TargetOSVersion, this.TargetArchitecture);
if (this.NativeCompiler == null) {
this.NativeCompiler = nativeContext.Compiler;
}
// We embed:
// - the assemblies (with their configuration)
// - the machine configuration
//
// For every embedded assembly, we store:
// - the name of the assembly
// - the pretty name of the assembly (for inclusion in source code)
// - the path to the static library that embed the assembly
// - the path to the static library that embed the assembly configuration file
List<Dictionary<String, String>> assemblies = new List<Dictionary<string, string>>();
List<Dictionary<String, String>> configurations = new List<Dictionary<string, string>>();
// Create an instance of creator
DataLibraryCreator creator = new DataLibraryCreator();
creator.Logger = this.Logger;
creator.ArchitectureFlags = nativeContext.ArchitectureFlags;
creator.OutputDirectory = directory;
this.Logger.LogInfo("Creating static libraries...");
// For each assembly and its config, generate a native library);
foreach (String assembly in this.Assemblies)
{
String name = Path.GetFileName(assembly);
this.Logger.LogInfo("Processing static library " + name);
Dictionary<string, string> bundle = CreateBundle(creator, assembly, false);
assemblies.Add(bundle);
String config = assembly + ".config";
if (File.Exists(config))
{
this.Logger.LogInfo("Processing configuration for " + name);
bundle = CreateBundle(creator, config, true);
bundle[KEY_ASSEMBLY] = name;
configurations.Add(bundle);
}
}
// Store the main image
String mainImage = assemblies[0][KEY_NAME];
// Sort all the symbols
assemblies.Sort((D1, D2) => D1[KEY_SYMBOL].CompareTo(D2[KEY_SYMBOL]));
configurations.Sort((D1, D2) => D1[KEY_SYMBOL].CompareTo(D2[KEY_SYMBOL]));
// Generate a native library for the machine configuration
Dictionary<String, String> machineConfig = null;
if (this.MachineConfiguration != null)
{
machineConfig = CreateBundle(creator, this.MachineConfiguration, true);
}
this.Logger.LogInfo("Creating source file...");
// Generate the main source file
String mainSource = Path.Combine(directory, "main.c");
this.GenerateMainSource(mainSource, mainImage, assemblies, configurations, machineConfig);
// Dump the header file
nativeContext.WriteHeader(directory);
// Dump the library file
nativeContext.WriteLibrary(directory);
// Stage 1: Preparation of common properties
String mainObject = Path.Combine(directory, "main.o");
String executableFile = Path.Combine(directory, Path.GetFileNameWithoutExtension(mainImage));
String nativeOptions = String.Format(" {0} {1} ", nativeContext.ArchitectureFlags, nativeContext.SDKFlags);
// Stage 2: Compilation
this.Compile(directory, mainSource, mainObject, nativeOptions);
// Stage 3: Linkage
this.Link(directory, mainObject, executableFile, nativeOptions, assemblies, configurations, machineConfig);
this.Logger.LogInfo("Embedding done");
return executableFile;
}
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(); }