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
 |