UNPKG

makit

Version:

Make in JavaScript done right!

129 lines (128 loc) 4.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Makefile = void 0; const rule_1 = require("./rule"); const make_1 = require("../make"); const logger_1 = require("../utils/logger"); const prerequisites_1 = require("./prerequisites"); const rude_1 = require("./rude"); const target_1 = require("./target"); const process_1 = require("process"); const recipe_1 = require("./recipe"); const dot_reporter_1 = require("../reporters/dot-reporter"); const defaultRecipe = () => void (0); const logger = logger_1.Logger.getOrCreate(); /** * 给最终使用者的 makefile.js 中暴露的全局变量 makit 即为 Makefile 实例 */ class Makefile { constructor(root = process_1.cwd(), reporter = new dot_reporter_1.DotReporter()) { this.disableCheckCircular = false; this.ruleMap = new Map(); this.fileTargetRules = new Map(); this.matchingRules = []; this.root = root; this.reporter = reporter; this.makeImpl = new make_1.Make({ root: this.root, reporter: this.reporter, matchRule: target => this.matchRule(target), disableCheckCircular: this.disableCheckCircular }); } updateOrAddRule(targetDecl, prerequisitesDecl = [], recipeDecl = defaultRecipe) { if (this.ruleMap.has(targetDecl)) { this.updateRule(targetDecl, prerequisitesDecl, recipeDecl); } else { this.addRule(targetDecl, prerequisitesDecl, recipeDecl); } } addRule(targetDecl, prerequisitesDecl = [], recipeDecl = defaultRecipe) { const target = new target_1.Target(targetDecl); const prerequisites = new prerequisites_1.Prerequisites(prerequisitesDecl); const recipe = new recipe_1.Recipe(recipeDecl); const rule = new rule_1.Rule(target, prerequisites, recipe); logger.verbose('RULE', 'adding rule', rule); if (target.isFilePath()) { this.fileTargetRules.set(target.decl, rule); } else { this.matchingRules.push(rule); } this.ruleMap.set(target.decl, rule); return rule; } addRude(targetDecl, prerequisitesDecl = [], recipeDecl = defaultRecipe) { if (targetDecl instanceof RegExp) throw new Error('rude() for RegExp not supported yet'); const rule = this.addRule(targetDecl, [prerequisitesDecl, '$0' + rude_1.rudeExtname], recipeDecl); rule.hasDynamicDependencies = true; this.addRule(rude_1.getDependencyFromTarget(targetDecl), rude_1.dynamicPrerequisites, rude_1.clearDynamicDependencies); } updateRule(targetDecl, prerequisitesDecl = [], recipeDecl = defaultRecipe) { const rule = this.ruleMap.get(targetDecl); if (!rule) { throw new Error(`rule for "${targetDecl}" not found`); } rule.prerequisites = new prerequisites_1.Prerequisites(prerequisitesDecl); rule.recipe = new recipe_1.Recipe(recipeDecl); } /** * makit 命令入口 * * 命令行调用 makit <target> 由本方法处理,具体的依赖递归解决由 Make 对象处理。 */ async make(target) { logger.resume(); if (!target) { target = this.findFirstTargetOrThrow(); } try { return await this.makeImpl.make(target); } catch (err) { // logger.suspend() if (err.target) { const chain = this.makeImpl.dependencyGraph.findPathToRoot(err.target); const target = chain.shift(); err.message = `${err.message} while making "${target}"`; for (const dep of chain) err.message += `\n required by "${dep}"`; } throw err; } } invalidate(target) { this.makeImpl.invalidate(target); } dependencyGraphString() { return this.makeImpl.dependencyGraph.toString(); } matchRule(target) { if (this.fileTargetRules.has(target)) { const match = [target]; match.input = target; match.index = 0; return [this.fileTargetRules.get(target), match]; } for (let i = this.matchingRules.length - 1; i >= 0; i--) { const rule = this.matchingRules[i]; const match = rule.match(target); if (match) { return [rule, match]; } } return null; } findFirstTarget() { return this.fileTargetRules.keys().next().value; } findFirstTargetOrThrow() { const target = this.findFirstTarget(); if (!target) throw new Error('target not found'); return target; } } exports.Makefile = Makefile;