forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			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
 |