public void GenerateBundledAssembly(string assemblyFile, string outputFile, out string configFile) { var assemblyName = Symbols.GetBundledAssemblyName(assemblyFile, Log); var assemblyConfigFileCopy = Path.Combine(Path.GetDirectoryName(outputFile), assemblyName) + ".config"; var configName = (assemblyName + ".config").ToLower(); try { configFile = ConfigFiles.First(t => Path.GetFileName(t.ItemSpec ?? "").ToLower() == configName).ItemSpec; } catch { configFile = null; } if (SkipUnchanged && File.Exists(outputFile) && File.Exists(assemblyFile) && File.GetLastWriteTime(outputFile) >= File.GetLastWriteTime(assemblyFile)) { if (configFile == null && !File.Exists(assemblyConfigFileCopy) || configFile != null && File.Exists(assemblyConfigFileCopy) && File.GetLastWriteTime(configFile) >= File.GetLastWriteTime(assemblyConfigFileCopy)) { Log.LogDebugMessage(" Not regenerating bundle file for unchanged assembly: {0}", assemblyFile); return; } } Log.LogDebugMessage($" Generating output '{outputFile}' from assembly '{assemblyFile}'"); var bundledAssemblyGetter = Symbols.GetBundledAssemblyGetter(assemblyName); var bundledAssemblyConfigGetter = Symbols.GetBundledAssemblyConfigGetter(assemblyName); var bundledAssemblyCleanup = Symbols.GetBundledAssemblyCleanup(assemblyName); using (var ins = File.OpenRead(assemblyFile)) { using (var outs = new StreamWriter(File.Create(outputFile))) { outs.WriteLine("static const unsigned char bundle_data [] = {"); WriteFileAsCArray(ins, outs); outs.WriteLine("};"); outs.WriteLine("typedef struct { const char* name; const unsigned char* data; const unsigned int size; } MonoBundledAssembly;"); outs.WriteLine($"static const MonoBundledAssembly bundle = {{\"{assemblyName}\", bundle_data, sizeof (bundle_data)}};"); outs.WriteLine($"const MonoBundledAssembly *{bundledAssemblyGetter} (void) {{ return &bundle; }}"); outs.WriteLine("typedef struct { const char* name; const char* data; } MonoBundledAssemblyConfig;"); if (configFile != null) { try { using (var cfgs = File.OpenRead(configFile)) { Log.LogDebugMessage($" Found assembly config file '{configFile}' for assembly '{assemblyFile}'"); outs.WriteLine("static const char config_data [] = {"); WriteFileAsCArray(cfgs, outs); outs.WriteLine("0};"); outs.WriteLine($"static const MonoBundledAssemblyConfig config = {{\"{assemblyName}\", config_data}};"); } } catch { // Return NULL if the assembly has no config file. configFile = null; } } if (configFile == null) { Log.LogDebugMessage($" No assembly config file found for assembly '{assemblyFile}'"); outs.WriteLine($"static const MonoBundledAssemblyConfig config = {{\"{assemblyName}\", 0L}};"); } if (File.Exists(assemblyConfigFileCopy)) { File.Delete(assemblyConfigFileCopy); } if (configFile != null) { File.Copy(configFile, assemblyConfigFileCopy); } outs.WriteLine($"const MonoBundledAssemblyConfig *{bundledAssemblyConfigGetter} (void) {{ return &config; }}"); // Cleanup function does nothing for now. Will be needed for compressed bundled. outs.WriteLine($"void {bundledAssemblyCleanup} (void) {{ return; }}"); } } }