292 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			292 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, "__esModule", { value: true });
							 | 
						||
| 
								 | 
							
								exports.Project = exports.Target = exports.Library = void 0;
							 | 
						||
| 
								 | 
							
								const child_process = require("child_process");
							 | 
						||
| 
								 | 
							
								const fs = require("fs");
							 | 
						||
| 
								 | 
							
								const path = require("path");
							 | 
						||
| 
								 | 
							
								const log = require("./log");
							 | 
						||
| 
								 | 
							
								const ProjectFile_1 = require("./ProjectFile");
							 | 
						||
| 
								 | 
							
								class Library {
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.Library = Library;
							 | 
						||
| 
								 | 
							
								class Target {
							 | 
						||
| 
								 | 
							
								    constructor(baseTarget, backends) {
							 | 
						||
| 
								 | 
							
								        this.baseTarget = baseTarget;
							 | 
						||
| 
								 | 
							
								        this.backends = backends;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.Target = Target;
							 | 
						||
| 
								 | 
							
								function contains(main, sub) {
							 | 
						||
| 
								 | 
							
								    main = path.resolve(main);
							 | 
						||
| 
								 | 
							
								    sub = path.resolve(sub);
							 | 
						||
| 
								 | 
							
								    if (process.platform === 'win32') {
							 | 
						||
| 
								 | 
							
								        main = main.toLowerCase();
							 | 
						||
| 
								 | 
							
								        sub = sub.toLowerCase();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return sub.indexOf(main) === 0 && sub.slice(main.length)[0] === path.sep;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								class Project {
							 | 
						||
| 
								 | 
							
								    constructor(name) {
							 | 
						||
| 
								 | 
							
								        this.icon = null;
							 | 
						||
| 
								 | 
							
								        this.name = name;
							 | 
						||
| 
								 | 
							
								        this.safeName = name.replace(/[^A-z0-9\-\_]/g, '-');
							 | 
						||
| 
								 | 
							
								        this.version = '1.0';
							 | 
						||
| 
								 | 
							
								        this.sources = [];
							 | 
						||
| 
								 | 
							
								        this.defines = ['hxcpp_smart_strings'];
							 | 
						||
| 
								 | 
							
								        this.cdefines = [];
							 | 
						||
| 
								 | 
							
								        this.cflags = [];
							 | 
						||
| 
								 | 
							
								        this.cppflags = [];
							 | 
						||
| 
								 | 
							
								        this.parameters = [];
							 | 
						||
| 
								 | 
							
								        this.scriptdir = Project.scriptdir;
							 | 
						||
| 
								 | 
							
								        this.libraries = [];
							 | 
						||
| 
								 | 
							
								        this.localLibraryPath = 'Libraries';
							 | 
						||
| 
								 | 
							
								        this.assetMatchers = [];
							 | 
						||
| 
								 | 
							
								        this.shaderMatchers = [];
							 | 
						||
| 
								 | 
							
								        this.customTargets = new Map();
							 | 
						||
| 
								 | 
							
								        this.stackSize = 0;
							 | 
						||
| 
								 | 
							
								        this.windowOptions = {};
							 | 
						||
| 
								 | 
							
								        this.targetOptions = {
							 | 
						||
| 
								 | 
							
								            html5: {},
							 | 
						||
| 
								 | 
							
								            flash: {},
							 | 
						||
| 
								 | 
							
								            android: {},
							 | 
						||
| 
								 | 
							
								            android_native: {},
							 | 
						||
| 
								 | 
							
								            ios: {},
							 | 
						||
| 
								 | 
							
								            xboxOne: {},
							 | 
						||
| 
								 | 
							
								            playStation4: {},
							 | 
						||
| 
								 | 
							
								            switch: {},
							 | 
						||
| 
								 | 
							
								            xboxSeriesXS: {},
							 | 
						||
| 
								 | 
							
								            playStation5: {},
							 | 
						||
| 
								 | 
							
								            stadia: {}
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    getSafeName() {
							 | 
						||
| 
								 | 
							
								        return this.safeName;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    async addProject(projectDir) {
							 | 
						||
| 
								 | 
							
								        if (!path.isAbsolute(projectDir)) {
							 | 
						||
| 
								 | 
							
								            projectDir = path.join(this.scriptdir, projectDir);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (!fs.existsSync(path.join(projectDir, 'khafile.js')) && (fs.existsSync(path.join(projectDir, 'kincfile.js')) || fs.existsSync(path.join(projectDir, 'korefile.js')) || fs.existsSync(path.join(projectDir, 'kfile.js')))) {
							 | 
						||
| 
								 | 
							
								            this.libraries.push({
							 | 
						||
| 
								 | 
							
								                libpath: projectDir,
							 | 
						||
| 
								 | 
							
								                libroot: projectDir
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else {
							 | 
						||
| 
								 | 
							
								            let project = await (0, ProjectFile_1.loadProject)(projectDir, 'khafile.js', Project.platform);
							 | 
						||
| 
								 | 
							
								            this.assetMatchers = this.assetMatchers.concat(project.assetMatchers);
							 | 
						||
| 
								 | 
							
								            this.sources = this.sources.concat(project.sources);
							 | 
						||
| 
								 | 
							
								            this.shaderMatchers = this.shaderMatchers.concat(project.shaderMatchers);
							 | 
						||
| 
								 | 
							
								            this.defines = this.defines.concat(project.defines);
							 | 
						||
| 
								 | 
							
								            this.cdefines = this.cdefines.concat(project.cdefines);
							 | 
						||
| 
								 | 
							
								            this.cflags = this.cflags.concat(project.cflags);
							 | 
						||
| 
								 | 
							
								            this.cppflags = this.cppflags.concat(project.cppflags);
							 | 
						||
| 
								 | 
							
								            this.parameters = this.parameters.concat(project.parameters);
							 | 
						||
| 
								 | 
							
								            this.libraries = this.libraries.concat(project.libraries);
							 | 
						||
| 
								 | 
							
								            if (this.icon === null && project.icon !== null)
							 | 
						||
| 
								 | 
							
								                this.icon = path.join(projectDir, project.icon);
							 | 
						||
| 
								 | 
							
								            for (let customTarget of project.customTargets.keys()) {
							 | 
						||
| 
								 | 
							
								                this.customTargets.set(customTarget, project.customTargets.get(customTarget));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            // windowOptions and targetOptions are ignored
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    unglob(str) {
							 | 
						||
| 
								 | 
							
								        const globChars = ['\\@', '\\!', '\\+', '\\*', '\\?', '\\(', '\\[', '\\{', '\\)', '\\]', '\\}'];
							 | 
						||
| 
								 | 
							
								        str = str.replace(/\\/g, '/');
							 | 
						||
| 
								 | 
							
								        for (const char of globChars) {
							 | 
						||
| 
								 | 
							
								            str = str.replace(new RegExp(char, 'g'), char);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return str;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    getBaseDir(str) {
							 | 
						||
| 
								 | 
							
								        // replace \\ to / if next char is not glob
							 | 
						||
| 
								 | 
							
								        str = str.replace(/\\([^@!+*?{}()[\]]|$)/g, '/$1');
							 | 
						||
| 
								 | 
							
								        // find non-globby path part
							 | 
						||
| 
								 | 
							
								        const globby = /[^\\][@!+*?{}()[\]]/;
							 | 
						||
| 
								 | 
							
								        while (globby.test(str)) {
							 | 
						||
| 
								 | 
							
								            str = path.posix.dirname(str);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        str = this.removeGlobEscaping(str);
							 | 
						||
| 
								 | 
							
								        if (!str.endsWith('/'))
							 | 
						||
| 
								 | 
							
								            str += '/';
							 | 
						||
| 
								 | 
							
								        return str;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    removeGlobEscaping(str) {
							 | 
						||
| 
								 | 
							
								        return str.replace(/\\([@!+*?{}()[\]]|$)/g, '$1');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Add all assets matching the match glob relative to the directory containing the current khafile.
							 | 
						||
| 
								 | 
							
								     * Asset types are infered from the file suffix.
							 | 
						||
| 
								 | 
							
								     * Glob syntax is very simple, the most important patterns are * for anything and ** for anything across directories.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    addAssets(match, options) {
							 | 
						||
| 
								 | 
							
								        if (!options)
							 | 
						||
| 
								 | 
							
								            options = {};
							 | 
						||
| 
								 | 
							
								        if (!path.isAbsolute(match)) {
							 | 
						||
| 
								 | 
							
								            let base = this.unglob(path.resolve(this.scriptdir));
							 | 
						||
| 
								 | 
							
								            if (!base.endsWith('/'))
							 | 
						||
| 
								 | 
							
								                base += '/';
							 | 
						||
| 
								 | 
							
								            // if there is no nameBaseDir: extract relative assets path from match
							 | 
						||
| 
								 | 
							
								            const baseName = options.nameBaseDir == null ? this.getBaseDir(match) : options.nameBaseDir;
							 | 
						||
| 
								 | 
							
								            match = path.posix.join(base, match.replace(/\\/g, '/'));
							 | 
						||
| 
								 | 
							
								            options.baseDir = path.posix.join(this.removeGlobEscaping(base), baseName);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else {
							 | 
						||
| 
								 | 
							
								            options.baseDir = this.getBaseDir(match);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        this.assetMatchers.push({ match: match, options: options });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addSources(source) {
							 | 
						||
| 
								 | 
							
								        this.sources.push(path.resolve(path.join(this.scriptdir, source)));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Add all shaders matching the match glob relative to the directory containing the current khafile.
							 | 
						||
| 
								 | 
							
								     * Glob syntax is very simple, the most important patterns are * for anything and ** for anything across directories.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    addShaders(match, options) {
							 | 
						||
| 
								 | 
							
								        if (!options)
							 | 
						||
| 
								 | 
							
								            options = {};
							 | 
						||
| 
								 | 
							
								        if (!path.isAbsolute(match)) {
							 | 
						||
| 
								 | 
							
								            let base = this.unglob(path.resolve(this.scriptdir));
							 | 
						||
| 
								 | 
							
								            if (!base.endsWith('/')) {
							 | 
						||
| 
								 | 
							
								                base += '/';
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            match = base + match.replace(/\\/g, '/');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        this.shaderMatchers.push({ match: match, options: options });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addDefine(define) {
							 | 
						||
| 
								 | 
							
								        this.defines.push(define);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addCDefine(define) {
							 | 
						||
| 
								 | 
							
								        this.cdefines.push(define);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addCFlag(flag) {
							 | 
						||
| 
								 | 
							
								        this.cflags.push(flag);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addCppFlag(flag) {
							 | 
						||
| 
								 | 
							
								        this.cppflags.push(flag);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addParameter(parameter) {
							 | 
						||
| 
								 | 
							
								        this.parameters.push(parameter);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addTarget(name, baseTarget, backends) {
							 | 
						||
| 
								 | 
							
								        this.customTargets.set(name, new Target(baseTarget, backends));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    addLibrary(library) {
							 | 
						||
| 
								 | 
							
								        this.addDefine(library);
							 | 
						||
| 
								 | 
							
								        let self = this;
							 | 
						||
| 
								 | 
							
								        function findLibraryDirectory(name) {
							 | 
						||
| 
								 | 
							
								            if (path.isAbsolute(name)) {
							 | 
						||
| 
								 | 
							
								                return { libpath: name, libroot: name };
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            // Tries to load the default library from inside the kha project.
							 | 
						||
| 
								 | 
							
								            // e.g. 'Libraries/wyngine'
							 | 
						||
| 
								 | 
							
								            let libpath = path.join(self.scriptdir, self.localLibraryPath, name);
							 | 
						||
| 
								 | 
							
								            if (fs.existsSync(libpath) && fs.statSync(libpath).isDirectory()) {
							 | 
						||
| 
								 | 
							
								                let dir = path.resolve(libpath);
							 | 
						||
| 
								 | 
							
								                return { libpath: dir, libroot: dir };
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            // If the library couldn't be found in Libraries folder, try
							 | 
						||
| 
								 | 
							
								            // looking in the haxelib folders.
							 | 
						||
| 
								 | 
							
								            // e.g. addLibrary('hxcpp') => '/usr/lib/haxelib/hxcpp/3,2,193'
							 | 
						||
| 
								 | 
							
								            try {
							 | 
						||
| 
								 | 
							
								                libpath = path.join(child_process.execSync('haxelib config', { encoding: 'utf8' }).trim(), name.replace(/\./g, ','));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            catch (error) {
							 | 
						||
| 
								 | 
							
								                if (process.env.HAXEPATH) {
							 | 
						||
| 
								 | 
							
								                    libpath = path.join(process.env.HAXEPATH, 'lib', name.toLowerCase());
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (fs.existsSync(libpath) && fs.statSync(libpath).isDirectory()) {
							 | 
						||
| 
								 | 
							
								                if (fs.existsSync(path.join(libpath, '.dev'))) {
							 | 
						||
| 
								 | 
							
								                    libpath = fs.readFileSync(path.join(libpath, '.dev'), 'utf8');
							 | 
						||
| 
								 | 
							
								                    if (!path.isAbsolute(libpath)) {
							 | 
						||
| 
								 | 
							
								                        libpath = path.resolve(libpath);
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                    return { libpath: libpath, libroot: libpath };
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else if (fs.existsSync(path.join(libpath, '.current'))) {
							 | 
						||
| 
								 | 
							
								                    // Get the latest version of the haxelib path,
							 | 
						||
| 
								 | 
							
								                    // e.g. for 'hxcpp', latest version '3,2,193'
							 | 
						||
| 
								 | 
							
								                    let current = fs.readFileSync(path.join(libpath, '.current'), 'utf8');
							 | 
						||
| 
								 | 
							
								                    return { libpath: path.join(libpath, current.replace(/\./g, ',')), libroot: libpath };
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            // check relative path
							 | 
						||
| 
								 | 
							
								            if (fs.existsSync(path.resolve(name))) {
							 | 
						||
| 
								 | 
							
								                let libpath = path.resolve(name);
							 | 
						||
| 
								 | 
							
								                return { libpath: libpath, libroot: libpath };
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            // Show error if library isn't found in Libraries or haxelib folder
							 | 
						||
| 
								 | 
							
								            log.error('Error: Library ' + name + ' not found.');
							 | 
						||
| 
								 | 
							
								            log.error('Add it to the \'Libraries\' subdirectory of your project. You may also install it via haxelib but that\'s less cool.');
							 | 
						||
| 
								 | 
							
								            throw 'Library ' + name + ' not found.';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        let libInfo = findLibraryDirectory(library);
							 | 
						||
| 
								 | 
							
								        let dir = libInfo.libpath;
							 | 
						||
| 
								 | 
							
								        if (dir !== '') {
							 | 
						||
| 
								 | 
							
								            for (let elem of this.libraries) {
							 | 
						||
| 
								 | 
							
								                if (elem.libroot === libInfo.libroot)
							 | 
						||
| 
								 | 
							
								                    return '';
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            this.libraries.push({
							 | 
						||
| 
								 | 
							
								                libpath: dir,
							 | 
						||
| 
								 | 
							
								                libroot: libInfo.libroot
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								            // If this is a haxelib library, there must be a haxelib.json
							 | 
						||
| 
								 | 
							
								            if (fs.existsSync(path.join(dir, 'haxelib.json'))) {
							 | 
						||
| 
								 | 
							
								                let options = JSON.parse(fs.readFileSync(path.join(dir, 'haxelib.json'), 'utf8'));
							 | 
						||
| 
								 | 
							
								                // If there is a classPath value, add that directory to be loaded.
							 | 
						||
| 
								 | 
							
								                // Otherwise, just load the current path.
							 | 
						||
| 
								 | 
							
								                if (options.classPath) {
							 | 
						||
| 
								 | 
							
								                    // TODO find an example haxelib that has a classPath value
							 | 
						||
| 
								 | 
							
								                    this.sources.push(path.join(dir, options.classPath));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                else {
							 | 
						||
| 
								 | 
							
								                    // e.g. '/usr/lib/haxelib/hxcpp/3,2,193'
							 | 
						||
| 
								 | 
							
								                    this.sources.push(dir);
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                // If this haxelib has other library dependencies, add them too
							 | 
						||
| 
								 | 
							
								                if (options.dependencies) {
							 | 
						||
| 
								 | 
							
								                    for (let dependency in options.dependencies) {
							 | 
						||
| 
								 | 
							
								                        if (dependency.toLowerCase() !== 'kha') {
							 | 
						||
| 
								 | 
							
								                            this.addLibrary(dependency);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else {
							 | 
						||
| 
								 | 
							
								                // If there is no haxelib.json file, then just load the library
							 | 
						||
| 
								 | 
							
								                // by the Sources folder.
							 | 
						||
| 
								 | 
							
								                // e.g. Libraries/wyngine/Sources
							 | 
						||
| 
								 | 
							
								                if (!fs.existsSync(path.join(dir, 'Sources'))) {
							 | 
						||
| 
								 | 
							
								                    log.info('Warning: No haxelib.json and no Sources directory found in library ' + library + '.');
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                this.sources.push(path.join(dir, 'Sources'));
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (fs.existsSync(path.join(dir, 'extraParams.hxml'))) {
							 | 
						||
| 
								 | 
							
								                let params = fs.readFileSync(path.join(dir, 'extraParams.hxml'), 'utf8');
							 | 
						||
| 
								 | 
							
								                for (let parameter of params.split('\n')) {
							 | 
						||
| 
								 | 
							
								                    let param = parameter.trim();
							 | 
						||
| 
								 | 
							
								                    if (param !== '') {
							 | 
						||
| 
								 | 
							
								                        if (param.startsWith('-lib')) {
							 | 
						||
| 
								 | 
							
								                            // (DK)
							 | 
						||
| 
								 | 
							
								                            //  - '-lib xxx' is for linking a library via haxe, it forces the use of the haxelib version
							 | 
						||
| 
								 | 
							
								                            //  - this should be handled by khamake though, as it tracks the dependencies better (local folder or haxelib)
							 | 
						||
| 
								 | 
							
								                            log.info('Ignoring ' + dir + '/extraParams.hxml "' + param + '"');
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                        else {
							 | 
						||
| 
								 | 
							
								                            this.addParameter(param);
							 | 
						||
| 
								 | 
							
								                        }
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            this.addShaders(dir + '/Sources/Shaders/**', {});
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return dir;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.Project = Project;
							 | 
						||
| 
								 | 
							
								//# sourceMappingURL=Project.js.map
							 |