"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.close = exports.run = exports.api = void 0; const child_process = require("child_process"); const fs = require("fs-extra"); const path = require("path"); const exec_1 = require("./exec"); const korepath = require("./korepath"); const log = require("./log"); const Platform_1 = require("./Platform"); const ProjectFile_1 = require("./ProjectFile"); const AssetConverter_1 = require("./AssetConverter"); const HaxeCompiler_1 = require("./HaxeCompiler"); const ShaderCompiler_1 = require("./ShaderCompiler"); const DebugHtml5Exporter_1 = require("./Exporters/DebugHtml5Exporter"); const EmptyExporter_1 = require("./Exporters/EmptyExporter"); const FlashExporter_1 = require("./Exporters/FlashExporter"); const Html5Exporter_1 = require("./Exporters/Html5Exporter"); const Html5WorkerExporter_1 = require("./Exporters/Html5WorkerExporter"); const JavaExporter_1 = require("./Exporters/JavaExporter"); const KincExporter_1 = require("./Exporters/KincExporter"); const KincHLExporter_1 = require("./Exporters/KincHLExporter"); const KromExporter_1 = require("./Exporters/KromExporter"); const NodeExporter_1 = require("./Exporters/NodeExporter"); const PlayStationMobileExporter_1 = require("./Exporters/PlayStationMobileExporter"); const WpfExporter_1 = require("./Exporters/WpfExporter"); const HaxeProject_1 = require("./HaxeProject"); const Icon = require("./Icon"); let lastAssetConverter; let lastShaderCompiler; let lastHaxeCompiler; function fixName(name) { name = name.replace(/[-@\ \.\/\\]/g, '_'); if (name[0] === '0' || name[0] === '1' || name[0] === '2' || name[0] === '3' || name[0] === '4' || name[0] === '5' || name[0] === '6' || name[0] === '7' || name[0] === '8' || name[0] === '9') { name = '_' + name; } return name; } function safeName(name) { return name.replace(/[^A-z0-9\-\_]/g, '-'); } function createKorefile(name, exporter, options, targetOptions, libraries, cdefines, cflags, cppflags, stackSize, version, id, korehl, icon) { let out = ''; out += 'let fs = require(\'fs\');\n'; out += 'let path = require(\'path\');\n'; out += 'let project = new Project(\'' + name + '\');\n'; if (version) { out += 'project.version = \'' + version + '\';\n'; } if (id) { out += 'project.id = \'' + id + '\';\n'; } if (icon != null) out += 'project.icon = \'' + icon + '\';\n'; for (let cdefine of cdefines) { out += 'project.addDefine(\'' + cdefine + '\');\n'; } for (let cppflag of cppflags) { out += 'project.addCppFlag(\'' + cppflag + '\');\n'; } for (let cflag of cflags) { out += 'project.addCFlag(\'' + cflag + '\');\n'; } out += 'project.addDefine(\'HXCPP_API_LEVEL=400\');\n'; out += 'project.addDefine(\'HXCPP_DEBUG\', \'Debug\');\n'; if (!options.slowgc) { out += 'project.addDefine(\'HXCPP_GC_GENERATIONAL\');\n'; } if (targetOptions) { let koreTargetOptions = {}; for (let option in targetOptions) { koreTargetOptions[option] = targetOptions[option]; } out += 'project.targetOptions = ' + JSON.stringify(koreTargetOptions) + ';\n'; } out += 'project.setDebugDir(\'' + path.relative(options.from, path.join(options.to, exporter.sysdir())).replace(/\\/g, '/') + '\');\n'; let buildpath = path.relative(options.from, path.join(options.to, exporter.sysdir() + '-build')).replace(/\\/g, '/'); if (buildpath.startsWith('..')) buildpath = path.resolve(path.join(options.from.toString(), buildpath)); out += 'await project.addProject(\'' + path.join(options.kha, 'Kinc').replace(/\\/g, '/') + '\');\n'; out += 'await project.addProject(\'' + buildpath.replace(/\\/g, '/') + '\');\n'; if (korehl) out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kinc-HL').replace(/\\/g, '/') + '\');\n'; else out += 'await project.addProject(\'' + path.join(options.kha, 'Backends', 'Kinc-hxcpp').replace(/\\/g, '/') + '\');\n'; for (let lib of libraries) { let libPath = lib.libpath.replace(/\\/g, '/'); out += 'if (fs.existsSync(path.join(\'' + libPath + '\', \'kfile.js\')) || fs.existsSync(path.join(\'' + libPath + '\', \'kincfile.js\')) || fs.existsSync(path.join(\'' + libPath + '\', \'korefile.js\'))) {\n'; out += '\tawait project.addProject(\'' + libPath + '\');\n'; out += '}\n'; } if (stackSize) { out += 'project.stackSize = ' + stackSize + ';\n'; } out += 'project.flatten();\n'; out += 'resolve(project);\n'; return out; } function runKmake(options) { return new Promise((resolve, reject) => { const child = child_process.spawn(path.join(korepath.get(), 'kmake' + (0, exec_1.sys)()), options); child.stdout.on('data', (data) => { const str = data.toString(); log.info(str, false); }); child.stderr.on('data', (data) => { const str = data.toString(); log.error(str, false); }); child.on('error', (err) => { log.error('Could not start kmake.'); reject(); }); child.on('close', (code) => { if (code === 0) { resolve(); } else { reject(); } }); }); } async function exportProjectFiles(name, resourceDir, options, exporter, kore, korehl, icon, libraries, targetOptions, defines, cdefines, cflags, cppflags, stackSize, version, id) { if (options.haxe !== '') { let haxeOptions = exporter.haxeOptions(name, targetOptions, defines); haxeOptions.defines.push('kha'); haxeOptions.defines.push('kha_version=1810'); haxeOptions.safeName = safeName(haxeOptions.name); haxeOptions.defines.push('kha_project_name=' + haxeOptions.name); if (options.livereload) haxeOptions.defines.push('kha_live_reload'); if (options.debug && haxeOptions.parameters.indexOf('-debug') < 0) { haxeOptions.parameters.push('-debug'); } (0, HaxeProject_1.writeHaxeProject)(options.to, !options.noproject, haxeOptions); if (!options.nohaxe) { let compiler = new HaxeCompiler_1.HaxeCompiler(options.to, haxeOptions.to, haxeOptions.realto, resourceDir, options.haxe, 'project-' + exporter.sysdir() + '.hxml', haxeOptions.sources, exporter.sysdir(), options.watchport, options.livereload, options.port); lastHaxeCompiler = compiler; try { await compiler.run(options.watch); } catch (error) { return Promise.reject(error); } } for (let callback of ProjectFile_1.Callbacks.postHaxeCompilation) { callback(); } await exporter.export(name, targetOptions, haxeOptions); } let buildDir = path.join(options.to, exporter.sysdir() + '-build'); if (options.haxe !== '' && kore && !options.noproject) { // If target is a Kore project, generate additional project folders here. // generate the kincfile.js fs.copySync(path.join(__dirname, '..', 'Data', 'hxcpp', 'kfile.js'), path.join(buildDir, 'kfile.js'), { overwrite: true }); fs.writeFileSync(path.join(options.to, 'kfile.js'), createKorefile(name, exporter, options, targetOptions, libraries, cdefines, cflags, cppflags, stackSize, version, id, false, icon)); // Similar to khamake.js -> main.js -> run(...) // We now do kincmake.js -> main.js -> run(...) // This will create additional project folders for the target, // e.g. 'build/pi-build' try { const kmakeOptions = ['--from', options.from, '--to', buildDir, '--kfile', path.resolve(options.to, 'kfile.js'), '-t', koreplatform(options.target), '--noshaders', '--graphics', options.graphics, '--arch', options.arch, '--audio', options.audio, '--vr', options.vr, '-v', options.visualstudio ]; if (options.nosigning) { kmakeOptions.push('--nosigning'); } if (options.debug) { kmakeOptions.push('--debug'); } if (options.run) { kmakeOptions.push('--run'); } if (options.compile) { kmakeOptions.push('--compile'); } await runKmake(kmakeOptions); for (let callback of ProjectFile_1.Callbacks.postCppCompilation) { callback(); } log.info('Done.'); return name; } catch (error) { if (error) { log.error('Error: ' + error); } else { log.error('Error.'); } process.exit(1); return name; } } else if (options.haxe !== '' && korehl && !options.noproject) { fs.copySync(path.join(__dirname, '..', 'Data', 'hl', 'kore_sources.c'), path.join(buildDir, 'kore_sources.c'), { overwrite: true }); fs.copySync(path.join(__dirname, '..', 'Data', 'hl', 'kfile.js'), path.join(buildDir, 'kfile.js'), { overwrite: true }); fs.writeFileSync(path.join(options.to, 'kfile.js'), createKorefile(name, exporter, options, targetOptions, libraries, cdefines, cflags, cppflags, stackSize, version, id, korehl, icon)); try { const kmakeOptions = ['--from', options.from, '--to', buildDir, '--kfile', path.resolve(options.to, 'kfile.js'), '-t', koreplatform(options.target), '--noshaders', '--graphics', options.graphics, '--arch', options.arch, '--audio', options.audio, '--vr', options.vr, '-v', options.visualstudio ]; if (options.nosigning) { kmakeOptions.push('--nosigning'); } if (options.debug) { kmakeOptions.push('--debug'); } if (options.run) { kmakeOptions.push('--run'); } if (options.compile) { kmakeOptions.push('--compile'); } await runKmake(kmakeOptions); for (let callback of ProjectFile_1.Callbacks.postCppCompilation) { callback(); } log.info('Done.'); return name; } catch (error) { if (error) { log.error('Error: ' + error); } else { log.error('Error.'); } process.exit(1); return name; } } else { // If target is not a Kore project, e.g. HTML5, finish building here. log.info('Done.'); return name; } } function checkKorePlatform(platform) { return platform === 'windows' || platform === 'windowsapp' || platform === 'ios' || platform === 'osx' || platform === 'android' || platform === 'linux' || platform === 'emscripten' || platform === 'pi' || platform === 'tvos' || platform === 'ps4' || platform === 'xboxone' || platform === 'switch' || platform === 'xboxscarlett' || platform === 'ps5' || platform === 'freebsd'; } function koreplatform(platform) { if (platform.endsWith('-hl')) return platform.substr(0, platform.length - '-hl'.length); else return platform; } let kore = false; let korehl = false; async function exportKhaProject(options) { log.info('Creating Kha project.'); let project = null; let foundProjectFile = false; // get the khafile.js and load the config code, // then create the project config object, which contains stuff // like project name, assets paths, sources path, library path... if (fs.existsSync(path.join(options.from, options.projectfile))) { try { project = await (0, ProjectFile_1.loadProject)(options.from, options.projectfile, options.target); } catch (x) { log.error(x); throw 'Loading the projectfile failed.'; } foundProjectFile = true; } if (!foundProjectFile) { throw 'No khafile found.'; } let temp = path.join(options.to, 'temp'); fs.ensureDirSync(temp); let exporter = null; let target = options.target.toLowerCase(); let baseTarget = target; let customTarget = null; if (project.customTargets.get(options.target)) { customTarget = project.customTargets.get(options.target); baseTarget = customTarget.baseTarget; } switch (baseTarget) { case Platform_1.Platform.Krom: exporter = new KromExporter_1.KromExporter(options); break; case Platform_1.Platform.Flash: exporter = new FlashExporter_1.FlashExporter(options); break; case Platform_1.Platform.HTML5: exporter = new Html5Exporter_1.Html5Exporter(options); break; case Platform_1.Platform.HTML5Worker: exporter = new Html5WorkerExporter_1.Html5WorkerExporter(options); break; case Platform_1.Platform.DebugHTML5: exporter = new DebugHtml5Exporter_1.DebugHtml5Exporter(options); break; case Platform_1.Platform.WPF: exporter = new WpfExporter_1.WpfExporter(options); break; case Platform_1.Platform.Java: exporter = new JavaExporter_1.JavaExporter(options); break; case Platform_1.Platform.PlayStationMobile: exporter = new PlayStationMobileExporter_1.PlayStationMobileExporter(options); break; case Platform_1.Platform.Node: exporter = new NodeExporter_1.NodeExporter(options); break; case Platform_1.Platform.Empty: exporter = new EmptyExporter_1.EmptyExporter(options); break; default: if (baseTarget.endsWith('-hl')) { korehl = true; options.target = koreplatform(baseTarget); if (!checkKorePlatform(options.target)) { log.error(`Unknown platform: ${target} (baseTarget=$${baseTarget})`); return Promise.reject(''); } exporter = new KincHLExporter_1.KincHLExporter(options); } else { kore = true; options.target = koreplatform(baseTarget); if (!checkKorePlatform(options.target)) { log.error(`Unknown platform: ${target} (baseTarget=$${baseTarget})`); return Promise.reject(''); } exporter = new KincExporter_1.KincExporter(options); } break; } exporter.setSystemDirectory(target); let buildDir = path.join(options.to, exporter.sysdir() + '-build'); // Create the target build folder // e.g. 'build/pi' fs.ensureDirSync(path.join(options.to, exporter.sysdir())); let defaultWindowOptions = { width: 800, height: 600 }; let windowOptions = project.windowOptions ? project.windowOptions : defaultWindowOptions; exporter.setName(project.name); exporter.setWidthAndHeight('width' in windowOptions ? windowOptions.width : defaultWindowOptions.width, 'height' in windowOptions ? windowOptions.height : defaultWindowOptions.height); for (let source of project.sources) { exporter.addSourceDirectory(source); } for (let library of project.libraries) { exporter.addLibrary(library); } exporter.parameters = exporter.parameters.concat(project.parameters); project.scriptdir = options.kha; if (baseTarget !== Platform_1.Platform.Java && baseTarget !== Platform_1.Platform.WPF) { project.addShaders('Sources/Shaders/**', {}); } for (let callback of ProjectFile_1.Callbacks.preAssetConversion) { callback(); } let assetConverter = new AssetConverter_1.AssetConverter(exporter, options, project.assetMatchers); lastAssetConverter = assetConverter; let assets = await assetConverter.run(options.watch, temp); if ((target === Platform_1.Platform.DebugHTML5 && process.platform === 'win32') || target === Platform_1.Platform.HTML5) { Icon.exportIco(project.icon, path.join(options.to, exporter.sysdir(), 'favicon.ico'), options.from, options); } else if (target === Platform_1.Platform.DebugHTML5) { Icon.exportPng(project.icon, path.join(options.to, exporter.sysdir(), 'favicon.png'), 256, 256, 0xffffffff, true, options.from, options); } let shaderDir = path.join(options.to, exporter.sysdir() + '-resources'); for (let callback of ProjectFile_1.Callbacks.preShaderCompilation) { callback(); } fs.ensureDirSync(shaderDir); let oldResources = null; let recompileAllShaders = false; try { oldResources = JSON.parse(fs.readFileSync(path.join(options.to, exporter.sysdir() + '-resources', 'files.json'), 'utf8')); for (let file of oldResources.files) { if (file.type === 'shader') { if (!file.files || file.files.length === 0) { recompileAllShaders = true; break; } } } } catch (error) { } let exportedShaders = []; if (!options.noshaders) { if (fs.existsSync(path.join(options.from, 'Backends'))) { let libdirs = fs.readdirSync(path.join(options.from, 'Backends')); for (let ld in libdirs) { let libdir = path.join(options.from, 'Backends', libdirs[ld]); if (fs.statSync(libdir).isDirectory()) { let exe = path.join(libdir, 'krafix', 'krafix-' + options.target + '.exe'); if (fs.existsSync(exe)) { options.krafix = exe; } } } } let shaderCompiler = new ShaderCompiler_1.ShaderCompiler(exporter, baseTarget, options.krafix, shaderDir, temp, buildDir, options, project.shaderMatchers); lastShaderCompiler = shaderCompiler; try { if (baseTarget !== Platform_1.Platform.Java && baseTarget !== Platform_1.Platform.WPF) { exportedShaders = await shaderCompiler.run(options.watch, recompileAllShaders); } } catch (err) { return Promise.reject(err); } } function findShader(name) { let fallback = {}; fallback.files = []; fallback.inputs = []; fallback.outputs = []; fallback.uniforms = []; fallback.types = []; try { for (let file of oldResources.files) { if (file.type === 'shader' && file.name === fixName(name)) { return file; } } } catch (error) { return fallback; } return fallback; } let files = []; for (let asset of assets) { let file = { name: fixName(asset.name), files: asset.files, file_sizes: asset.file_sizes, type: asset.type }; if (file.type === 'image') { file.original_width = asset.original_width; file.original_height = asset.original_height; if (asset.readable) file.readable = asset.readable; } files.push(file); } for (let shader of exportedShaders) { if (shader.noembed) continue; let oldShader = findShader(shader.name); files.push({ name: fixName(shader.name), files: shader.files === null ? oldShader.files : shader.files, file_sizes: [1], type: 'shader', inputs: shader.inputs === null ? oldShader.inputs : shader.inputs, outputs: shader.outputs === null ? oldShader.outputs : shader.outputs, uniforms: shader.uniforms === null ? oldShader.uniforms : shader.uniforms, types: shader.types === null ? oldShader.types : shader.types }); } // Sort to prevent files.json from changing between makes when no files have changed. files.sort(function (a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; }); function secondPass() { // First pass is for main project files. Second pass is for shaders. // Will try to look for the folder, e.g. 'build/Shaders'. // if it exists, export files similar to other a let hxslDir = path.join('build', 'Shaders'); /** if (fs.existsSync(hxslDir) && fs.readdirSync(hxslDir).length > 0) { addShaders(exporter, platform, project, from, to.resolve(exporter.sysdir() + '-resources'), temp, from.resolve(Paths.get(hxslDir)), krafix); if (foundProjectFile) { fs.outputFileSync(to.resolve(Paths.get(exporter.sysdir() + '-resources', 'files.json')).toString(), JSON.stringify({ files: files }, null, '\t'), { encoding: 'utf8' }); log.info('Assets done.'); exportProjectFiles(name, from, to, options, exporter, platform, khaDirectory, haxeDirectory, kore, project.libraries, project.targetOptions, callback); } else { exportProjectFiles(name, from, to, options, exporter, platform, khaDirectory, haxeDirectory, kore, project.libraries, project.targetOptions, callback); } }*/ } if (foundProjectFile) { fs.outputFileSync(path.join(options.to, exporter.sysdir() + '-resources', 'files.json'), JSON.stringify({ files: files }, null, '\t')); } for (let callback of ProjectFile_1.Callbacks.preHaxeCompilation) { callback(); } return await exportProjectFiles(project.name, path.join(options.to, exporter.sysdir() + '-resources'), options, exporter, kore, korehl, project.icon, project.libraries, project.targetOptions, project.defines, project.cdefines, project.cflags, project.cppflags, project.stackSize, project.version, project.id); } function isKhaProject(directory, projectfile) { return fs.existsSync(path.join(directory, 'Kha')) || fs.existsSync(path.join(directory, projectfile)); } async function exportProject(options) { if (isKhaProject(options.from, options.projectfile)) { return await exportKhaProject(options); } else { log.error('Neither Kha directory nor project file (' + options.projectfile + ') found.'); return 'Unknown'; } } function runProject(options, name) { return new Promise((resolve, reject) => { log.info('Running...'); let run = child_process.spawn(path.join(process.cwd(), options.to, 'linux-build', name), [], { cwd: path.join(process.cwd(), options.to, 'linux') }); run.stdout.on('data', function (data) { log.info(data.toString()); }); run.stderr.on('data', function (data) { log.error(data.toString()); }); run.on('close', function (code) { resolve(); }); }); } exports.api = 2; function findKhaVersion(dir) { let p = path.join(dir, '.git'); let hasGitInfo = false; if (fs.existsSync(p)) { let stat = fs.statSync(p); hasGitInfo = stat.isDirectory(); // otherwise git might not utilize an in-place directory if (!hasGitInfo) { let contents = fs.readFileSync(p).toString('utf8', 0, 7); hasGitInfo = contents === 'gitdir:'; } } if (hasGitInfo) { let gitVersion = 'git-error'; try { const output = child_process.spawnSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8', cwd: dir }).output; for (const str of output) { if (str != null && str.length > 0) { gitVersion = str.substr(0, 8); break; } } } catch (error) { } let gitStatus = 'git-error'; try { const output = child_process.spawnSync('git', ['status', '--porcelain'], { encoding: 'utf8', cwd: dir }).output; gitStatus = ''; for (const str of output) { if (str != null && str.length > 0) { gitStatus = str.trim(); break; } } } catch (error) { } if (gitStatus) { return gitVersion + ', ' + gitStatus.replace(/\n/g, ','); } else { return gitVersion; } } else { return '¯\\_(ツ)_/¯'; } } async function run(options, loglog) { if (options.silent) { log.silent(); } else { log.set(loglog); } if (options.quiet) { log.silent(true); } if (!options.kha) { let p = path.join(__dirname, '..', '..', '..'); if (fs.existsSync(p) && fs.statSync(p).isDirectory()) { options.kha = p; } } else { options.kha = path.resolve(options.kha); } log.info('Using Kha (' + findKhaVersion(options.kha) + ') from ' + options.kha); if (options.parallelAssetConversion === undefined) { options.parallelAssetConversion = 0; } if (!options.haxe) { let haxepath = path.join(options.kha, 'Tools', (0, exec_1.sysdir)()); if (fs.existsSync(haxepath) && fs.statSync(haxepath).isDirectory()) options.haxe = haxepath; } if (!options.krafix) { let krafixpath = path.join(options.kha, 'Kinc', 'Tools', (0, exec_1.sysdir)(), 'krafix' + (0, exec_1.sys)()); if (fs.existsSync(krafixpath)) options.krafix = krafixpath; } if (!options.kraffiti) { const kraffitipath = path.join(options.kha, 'Kinc', 'Tools', (0, exec_1.sysdir)(), 'kraffiti' + (0, exec_1.sys)()); if (fs.existsSync(kraffitipath)) options.kraffiti = kraffitipath; } else { log.info('Using kraffiti from ' + options.kraffiti); } if (!options.ogg && options.ffmpeg) { options.ogg = options.ffmpeg + ' -nostdin -i {in} {out} -y'; } if (!options.mp3 && options.ffmpeg) { options.mp3 = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (!options.ogg) { let oggpath = path.join(options.kha, 'Tools', (0, exec_1.sysdir)(), 'oggenc' + (0, exec_1.sys)()); if (fs.existsSync(oggpath)) options.ogg = oggpath + ' {in} -o {out} --quiet'; } if (!options.mp3) { let lamepath = path.join(options.kha, 'Tools', (0, exec_1.sysdir)(), 'lame' + (0, exec_1.sys)()); if (fs.existsSync(lamepath)) options.mp3 = lamepath + ' {in} {out}'; } // if (!options.kravur) { // let kravurpath = path.join(options.kha, 'Tools', 'kravur', 'kravur' + sys()); // if (fs.existsSync(kravurpath)) options.kravur = kravurpath + ' {in} {size} {out}'; // } if (!options.aac && options.ffmpeg) { options.aac = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (!options.h264 && options.ffmpeg) { options.h264 = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (!options.webm && options.ffmpeg) { options.webm = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (!options.wmv && options.ffmpeg) { options.wmv = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (!options.theora && options.ffmpeg) { options.theora = options.ffmpeg + ' -nostdin -i {in} {out}'; } if (options.target === 'emscripten') { console.log(); console.log('Please note that the html5 target\n' + 'is usually a better choice.\n' + 'In particular the html5 target usually runs faster\n' + 'than the emscripten target. That is because\n' + 'Haxe and JavaScript are similar in many ways and\n' + 'therefore the html5 target can make direct use of\n' + 'all of the optimizations in modern JavaScript\n' + 'runtimes. The emscripten target on the other hand\n' + 'has to provide its own garbage collector and many\n' + 'other performance critical pieces of infrastructure.'); console.log(); } let name = ''; try { name = await exportProject(options); } catch (err) { for (let callback of ProjectFile_1.Callbacks.onFailure) { callback(err); } throw err; } for (let callback of ProjectFile_1.Callbacks.postBuild) { callback(); } if ((options.target === Platform_1.Platform.Linux || options.target === Platform_1.Platform.FreeBSD) && options.run) { await runProject(options, name); } return name; } exports.run = run; function close() { if (lastAssetConverter) lastAssetConverter.close(); if (lastShaderCompiler) lastShaderCompiler.close(); if (lastHaxeCompiler) lastHaxeCompiler.close(); } exports.close = close; //# sourceMappingURL=main.js.map