public abstract Dictionary <string, FileOutput> Package( BuildContext buildContext, string projectId, Dictionary <string, Executable[]> finalCode, ICollection <StructDefinition> structDefinitions, string fileCopySourceRoot, ResourceDatabase resourceDatabase, SystemLibraryManager libraryManager);
private static void ExportVmBundle(Dictionary <string, string> argLookup) { using (new PerformanceSection("ExportVmBundle")) { BuildContext buildContext = GetBuildContext(argLookup); Platform.AbstractPlatform platform = GetPlatformInstance(buildContext); if (platform == null) { throw new InvalidOperationException("Unrecognized platform. See usage."); } CompilationBundle compilationResult = CompilationBundle.Compile(buildContext); // Need to re-instantiate the libraries. The libraries are instantiated in a platform-context-free // for the purpose of compiling the byte code. For the VM bundle, they need to know about the platform. Library[] libraries; using (new PerformanceSection("Program.ExportVmBundle.CloneLibraries")) { libraries = compilationResult.LibrariesUsed .Select(lib => lib.CloneWithNewPlatform(platform)) .ToArray(); } ResourceDatabase resourceDatabase = PrepareResources(buildContext, compilationResult.ByteCode); string outputDirectory = buildContext.OutputFolder; if (!FileUtil.IsAbsolutePath(outputDirectory)) { outputDirectory = FileUtil.JoinPath(buildContext.ProjectDirectory, outputDirectory); } outputDirectory = FileUtil.GetCanonicalizeUniversalPath(outputDirectory); FileOutputExporter exporter = new FileOutputExporter(outputDirectory); VmGenerator vmGenerator = new VmGenerator(); Dictionary <string, FileOutput> result = vmGenerator.GenerateVmSourceCodeForPlatform( platform, compilationResult, resourceDatabase, libraries, outputDirectory, VmGenerationMode.EXPORT_SELF_CONTAINED_PROJECT_SOURCE); exporter.ExportFiles(result); if (argLookup.ContainsKey(FlagParser.LIBRARY_DEP_TREE)) { string libs = LibraryDependencyResolver.GetDependencyTreeLog(compilationResult.LibrariesUsed.ToArray()); Console.WriteLine("<LibraryDependencies>"); Console.WriteLine(libs.Trim()); Console.WriteLine("</LibraryDependencies>"); } } }
public static ResourceDatabase PrepareResources( BuildContext buildContext, ByteBuffer nullableByteCode) // CBX files will not have this in the resources { using (new PerformanceSection("Program.PrepareResources")) { // This really needs to go in a separate helper file. ResourceDatabase resourceDatabase = ResourceDatabaseBuilder.CreateResourceDatabase(buildContext); if (nullableByteCode != null) { resourceDatabase.ByteCodeFile = new FileOutput() { Type = FileOutputType.Text, TextContent = ByteCodeEncoder.Encode(nullableByteCode), }; } using (new PerformanceSection("Program.PrepareResources/ImageSheetStuff")) { Common.ImageSheets.ImageSheetBuilder imageSheetBuilder = new Common.ImageSheets.ImageSheetBuilder(); if (buildContext.ImageSheetIds != null) { foreach (string imageSheetId in buildContext.ImageSheetIds) { imageSheetBuilder.PrefixMatcher.RegisterId(imageSheetId); foreach (string fileMatcher in buildContext.ImageSheetPrefixesById[imageSheetId]) { imageSheetBuilder.PrefixMatcher.RegisterPrefix(imageSheetId, fileMatcher); } } } Common.ImageSheets.Sheet[] imageSheets = imageSheetBuilder.Generate(resourceDatabase); resourceDatabase.AddImageSheets(imageSheets); } resourceDatabase.GenerateResourceMapping(); return(resourceDatabase); } }
public static ResourceDatabase CreateResourceDatabase(BuildContext buildContext) { using (new PerformanceSection("ResourceDatabaseBuilder.CreateResourceDatabase")) { ResourceDatabase resDb = new ResourceDatabase(); foreach (FilePath sourceRoot in buildContext.SourceFolders) { string[] relativePaths = FileUtil.GetAllFilePathsRelativeToRoot(sourceRoot.AbsolutePath); // Everything is just a basic copy resource at first. foreach (string relativeFilePath in relativePaths) { string absolutePath = FileUtil.GetCanonicalizeUniversalPath(sourceRoot.AbsolutePath + "/" + relativeFilePath); string aliasedPath = sourceRoot.GetAliasedOrRelativePathh(absolutePath); string fileName = System.IO.Path.GetFileName(absolutePath); string extension = FileUtil.GetCanonicalExtension(fileName) ?? ""; ResourceDatabase.FileCategory category; if (IGNORABLE_FILES.Contains(fileName.ToLowerInvariant())) { // Common system generated files that no one would ever want. category = ResourceDatabase.FileCategory.IGNORE_SILENT; } else if (ResourceDatabase.KNOWN_FILE_EXTENSIONS.ContainsKey(extension)) { category = ResourceDatabase.KNOWN_FILE_EXTENSIONS[extension]; } else { TODO.BuildFileShouldIndicateWhichResourcesAreTextVsBinary(); category = ResourceDatabase.FileCategory.TEXT; } switch (category) { case ResourceDatabase.FileCategory.IGNORE_SILENT: break; case ResourceDatabase.FileCategory.IGNORE_IMAGE: System.Console.WriteLine(aliasedPath + " is not a usable image type and is being ignored. Consider converting to PNG or JPEG."); break; case ResourceDatabase.FileCategory.IGNORE_AUDIO: System.Console.WriteLine(aliasedPath + " is not a usable audio format and is being ignored. Consider converting to OGG."); break; case ResourceDatabase.FileCategory.IGNORE_IMAGE_ASSET: System.Console.WriteLine(aliasedPath + " is an image asset container file type and is being ignored. Consider moving original assets outside of the source folder."); break; case ResourceDatabase.FileCategory.AUDIO: resDb.AudioResources.Add(new FileOutput() { Type = FileOutputType.Copy, RelativeInputPath = aliasedPath, OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); break; case ResourceDatabase.FileCategory.BINARY: resDb.AudioResources.Add(new FileOutput() { Type = FileOutputType.Copy, RelativeInputPath = aliasedPath, OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); break; case ResourceDatabase.FileCategory.TEXT: string content = FileUtil.ReadFileText(absolutePath); resDb.TextResources.Add(new FileOutput() { Type = FileOutputType.Text, TextContent = content, OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); break; case ResourceDatabase.FileCategory.IMAGE: TODO.GetImageDimensionsFromFirstFewBytesInsteadOfLoadingIntoMemory(); if (extension == "png") { // Re-encode PNGs into a common format/palette configuration since there are some issues // with obscure format PNGs on some platforms. Luckily the compiler is pretty good with // reading these. Besides, you're going to be opening most of these files anyway since // the user should be using image sheets. resDb.ImageResources.Add(new FileOutput() { Type = FileOutputType.Image, Bitmap = new SystemBitmap(absolutePath), OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); } else if (extension == "jpg" || extension == "jpeg") { resDb.ImageResources.Add(new FileOutput() { Type = FileOutputType.Image, Bitmap = new SystemBitmap(absolutePath), OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, IsLossy = true, }); } else { TODO.PutImageWidthAndHeightIntoFileOutputPropertiesSoThatBitmapDoesntNeedToBePersistedInMemory(); resDb.ImageResources.Add(new FileOutput() { Type = FileOutputType.Copy, Bitmap = new SystemBitmap(absolutePath), RelativeInputPath = aliasedPath, OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); } break; case ResourceDatabase.FileCategory.FONT: resDb.FontResources.Add(new FileOutput() { Type = FileOutputType.Copy, RelativeInputPath = aliasedPath, OriginalPath = aliasedPath, AbsoluteInputPath = absolutePath, }); break; default: throw new InvalidOperationException(); } } } return(resDb); } }
public Dictionary <string, FileOutput> GenerateVmSourceCodeForPlatform( Platform.AbstractPlatform platform, CompilationBundle nullableCompilationBundle, ResourceDatabase resourceDatabase, ICollection <Library> relevantLibraries, VmGenerationMode mode) { using (new PerformanceSection("VmGenerator.GenerateVmSourceCodeForPlatform")) { Options options = new Options(); Dictionary <string, object> constantFlags = platform.GetFlattenedConstantFlags() ?? new Dictionary <string, object>(); this.mode = mode; this.AddTypeEnumsToConstants(constantFlags); Pastel.PastelCompiler vm = this.GenerateCoreVmParseTree(platform, constantFlags); Dictionary <string, Library> librariesByName = relevantLibraries.ToDictionary(lib => lib.Name); List <Platform.LibraryForExport> libraries = this.GetLibrariesForExport(platform, librariesByName, constantFlags, vm); LibraryNativeInvocationTranslatorProvider libTranslationProvider = new LibraryNativeInvocationTranslatorProvider( relevantLibraries.ToDictionary(lib => lib.Name), platform); if (mode == VmGenerationMode.EXPORT_SELF_CONTAINED_PROJECT_SOURCE) { options .SetOption(ExportOptionKey.PROJECT_ID, nullableCompilationBundle.ProjectID) .SetOption(ExportOptionKey.DESCRIPTION, nullableCompilationBundle.Description) .SetOption(ExportOptionKey.VERSION, nullableCompilationBundle.Version) .SetOption(ExportOptionKey.EMBED_BYTE_CODE, nullableCompilationBundle.GuidSeed) .SetOption(ExportOptionKey.EMBED_BYTE_CODE, true) .SetOption(ExportOptionKey.DEFAULT_TITLE, nullableCompilationBundle.DefaultTitle) .SetOption(ExportOptionKey.LIBRARIES_USED, libraries.Cast <object>().ToArray()) .SetOption(ExportOptionKey.HAS_ICON, nullableCompilationBundle.IconPath != null) .SetOption(ExportOptionKey.IOS_BUNDLE_PREFIX, nullableCompilationBundle.IosBundlePrefix) .SetOption(ExportOptionKey.JS_FILE_PREFIX, nullableCompilationBundle.JsFilePrefix); if (options.GetBool(ExportOptionKey.HAS_ICON)) { options.SetOption(ExportOptionKey.ICON_PATH, nullableCompilationBundle.IconPath); } return(platform.ExportProject( vm.Globals.Values.OrderBy(v => v.VariableNameToken.Value).ToArray(), vm.StructDefinitions.Values.OrderBy(s => s.NameToken.Value).ToArray(), vm.FunctionDefinitions.Values.OrderBy(f => f.NameToken.Value).ToArray(), libraries, resourceDatabase, options, libTranslationProvider)); } else { return(platform.ExportStandaloneVm( vm.Globals.Values.OrderBy(v => v.VariableNameToken.Value).ToArray(), vm.StructDefinitions.Values.OrderBy(s => s.NameToken.Value).ToArray(), vm.FunctionDefinitions.Values.OrderBy(f => f.NameToken.Value).ToArray(), libraries, libTranslationProvider)); } } }
public void Compile( BuildContext buildContext, string inputFolder, string baseOutputFolder) { Parser.IsTranslateMode_STATIC_HACK = false; this.VerifyProjectId(buildContext.ProjectID); inputFolder = inputFolder.Replace('/', '\\'); if (inputFolder.EndsWith("\\")) { inputFolder = inputFolder.Substring(0, inputFolder.Length - 1); } string[] allFiles = FileUtil.GetAllFilePathsRelativeToRoot(inputFolder); ResourceDatabase resourceDatabase = new ResourceDatabase(allFiles, inputFolder); ImageSheets.ImageSheetBuilder imageSheetBuilder = new ImageSheets.ImageSheetBuilder(); if (buildContext.ImageSheetIds != null) { foreach (string imageSheetId in buildContext.ImageSheetIds) { imageSheetBuilder.PrefixMatcher.RegisterId(imageSheetId); foreach (string fileMatcher in buildContext.ImageSheetPrefixesById[imageSheetId]) { imageSheetBuilder.PrefixMatcher.RegisterPrefix(imageSheetId, fileMatcher); } } } ImageSheets.Sheet[] imageSheets = imageSheetBuilder.Generate(resourceDatabase); resourceDatabase.AddImageSheets(imageSheets); resourceDatabase.GenerateResourceMapping(); ByteBuffer byteCodeBuffer = GenerateByteCode(buildContext, inputFolder); resourceDatabase.ByteCodeRawData = byteCodeBuffer; resourceDatabase.ByteCodeFile = new FileOutput() { Type = FileOutputType.Text, TextContent = ByteCodeEncoder.Encode(byteCodeBuffer), }; Parser.IsTranslateMode_STATIC_HACK = true; Dictionary <string, Executable[]> executablesByFile = this.InterpreterCompiler.Compile(); Parser.IsTranslateMode_STATIC_HACK = false; StructDefinition[] structs = this.InterpreterCompiler.GetStructDefinitions(); Dictionary <string, FileOutput> files = this.Package( buildContext, buildContext.ProjectID, executablesByFile, structs, inputFolder, resourceDatabase, this.LibraryManager); if (buildContext.ReadableByteCode) { files["readable_byte_code.txt"] = new FileOutput() { Type = FileOutputType.Text, TextContent = this.GenerateReadableByteCode(byteCodeBuffer), }; } string outputFolder = baseOutputFolder; FileUtil.EnsureParentFolderExists(outputFolder); // TODO: delete all files and directories in the output folder that are not in the new output // which is better than deleting everything and re-exporting because the user may have command // lines and windows open viewing the previous content, which will prevent a full delete from // working, but won't stop a simple overwrite of old content. this.GenerateFiles(buildContext, files, outputFolder, inputFolder); }
public CbxExporter Export() { using (new PerformanceSection("ExportCbx")) { if (!this.args.ContainsKey(FlagParser.BUILD_FILE)) { throw new InvalidOperationException("No build path was provided."); } BuildContext buildContext = GetBuildContextCbx(this.args[FlagParser.BUILD_FILE]); CompilationBundle compilationResult = CompilationBundle.Compile(buildContext); ResourceDatabase resDb = Program.PrepareResources(buildContext, null); string byteCode = ByteCodeEncoder.Encode(compilationResult.ByteCode); List <byte> cbxOutput = new List <byte>() { 0 }; cbxOutput.AddRange("CBX".ToCharArray().Select(c => (byte)c)); cbxOutput.AddRange(GetBigEndian4Byte(0)); cbxOutput.AddRange(GetBigEndian4Byte(2)); cbxOutput.AddRange(GetBigEndian4Byte(0)); byte[] code = StringToBytes(byteCode); cbxOutput.AddRange("CODE".ToCharArray().Select(c => (byte)c)); cbxOutput.AddRange(GetBigEndian4Byte(code.Length)); cbxOutput.AddRange(code); List <string> libraries = new List <string>(); foreach (Library library in compilationResult.LibrariesUsed.Where(lib => lib.IsMoreThanJustEmbedCode)) { libraries.Add(library.Name); libraries.Add(library.Version); } string libsData = string.Join(",", libraries); byte[] libsDataBytes = StringToBytes(libsData); cbxOutput.AddRange("LIBS".ToCharArray().Select(c => (byte)c)); cbxOutput.AddRange(GetBigEndian4Byte(libsDataBytes.Length)); cbxOutput.AddRange(libsDataBytes); byte[] resourceManifest = StringToBytes(resDb.ResourceManifestFile.TextContent); cbxOutput.AddRange("RSRC".ToCharArray().Select(c => (byte)c)); cbxOutput.AddRange(GetBigEndian4Byte(resourceManifest.Length)); cbxOutput.AddRange(resourceManifest); if (resDb.ImageSheetManifestFile != null) { byte[] imageSheetManifest = StringToBytes(resDb.ImageSheetManifestFile.TextContent); cbxOutput.AddRange("IMSH".ToCharArray().Select(c => (byte)c)); cbxOutput.AddRange(GetBigEndian4Byte(imageSheetManifest.Length)); cbxOutput.AddRange(imageSheetManifest); } string outputFolder = buildContext.OutputFolder.Replace("%TARGET_NAME%", "cbx"); string fullyQualifiedOutputFolder = FileUtil.JoinPath(buildContext.ProjectDirectory, outputFolder); string cbxPath = FileUtil.JoinPath(fullyQualifiedOutputFolder, buildContext.ProjectID + ".cbx"); cbxPath = FileUtil.GetCanonicalizeUniversalPath(cbxPath); FileUtil.EnsureParentFolderExists(fullyQualifiedOutputFolder); Dictionary <string, FileOutput> output = new Dictionary <string, FileOutput>(); output[buildContext.ProjectID + ".cbx"] = new FileOutput() { Type = FileOutputType.Binary, BinaryContent = cbxOutput.ToArray(), }; // Resource manifest and image sheet manifest is embedded into the CBX file foreach (FileOutput txtResource in resDb.TextResources) { output["res/txt/" + txtResource.CanonicalFileName] = txtResource; } foreach (FileOutput sndResource in resDb.AudioResources) { output["res/snd/" + sndResource.CanonicalFileName] = sndResource; } foreach (FileOutput fontResource in resDb.FontResources) { output["res/ttf/" + fontResource.CanonicalFileName] = fontResource; } foreach (FileOutput binResource in resDb.BinaryResources) { output["res/bin/" + binResource.CanonicalFileName] = binResource; } foreach (FileOutput imgResource in resDb.ImageResources) { output["res/img/" + imgResource.CanonicalFileName] = imgResource; } foreach (string key in resDb.ImageSheetFiles.Keys) { output["res/img/" + key] = resDb.ImageSheetFiles[key]; } new FileOutputExporter(fullyQualifiedOutputFolder).ExportFiles(output); this.finalCbxPath = cbxPath; } return(this); }