UNPKG

@keymanapp/kmc

Version:

Keyman Developer compiler command line tools

117 lines 5.61 kB
import * as path from 'path'; import * as fs from 'fs'; import { CompilerFileCallbacks } from '@keymanapp/developer-utils'; import { KeymanDeveloperProjectType } from '@keymanapp/developer-utils'; import { BuildActivity } from './BuildActivity.js'; import { buildActivities, buildKeyboardInfoActivity, buildModelInfoActivity } from './buildActivities.js'; import { InfrastructureMessages } from '../../messages/infrastructureMessages.js'; import { loadProject } from '../../util/projectLoader.js'; import { getOption } from '@keymanapp/developer-utils'; export class BuildProject extends BuildActivity { get name() { return 'Project'; } get sourceExtension() { return ".kpj" /* KeymanFileTypes.Source.Project */; } get compiledExtension() { return null; } get description() { return 'Build a keyboard or lexical model project'; } async build(infile, outfile, callbacks, options) { if (outfile) { callbacks.reportMessage(InfrastructureMessages.Error_OutFileNotValidForProjects()); return false; } let builder = new ProjectBuilder(infile, callbacks, options); return builder.run(); } } class ProjectBuilder { callbacks; infile; options; project; constructor(infile, callbacks, options) { this.infile = path.resolve(infile); this.callbacks = new CompilerFileCallbacks(infile, options, callbacks); this.options = options; } async run() { this.project = await loadProject(this.infile, this.callbacks); if (!this.project) { return false; } // Give a hint if the project is v1.0 if (this.project.options.version != '2.0') { if (getOption("prompt to upgrade projects", true)) { this.callbacks.reportMessage(InfrastructureMessages.Hint_ProjectIsVersion10()); } } // Go through the various file types and build them for (let builder of buildActivities) { if (builder.sourceExtension == ".kpj" /* KeymanFileTypes.Source.Project */) { // We don't support nested projects continue; } if (!await this.buildProjectTargets(builder)) { return false; } } // Build project metadata if (this.options.forPublishing || !this.project.options.skipMetadataFiles) { let activity = null; // Determine activity type first of all by examining files in the project // Then if that is inconclusive, examine the declared project type if (this.project.isKeyboardProject()) { activity = buildKeyboardInfoActivity; } else if (this.project.isLexicalModelProject()) { activity = buildModelInfoActivity; } else if (this.project.options.projectType == KeymanDeveloperProjectType.Keyboard) { activity = buildKeyboardInfoActivity; } else if (this.project.options.projectType == KeymanDeveloperProjectType.LexicalModel) { activity = buildModelInfoActivity; } else { // If we get here, then we are not sure what type of project this is, so // we'll assume keyboard activity = buildKeyboardInfoActivity; } if (!await (this.buildProjectTargets(activity))) { return false; } } return true; } async buildProjectTargets(activity) { if (activity.sourceExtension == ".kpj" /* KeymanFileTypes.Source.Project */) { return await this.buildTarget(this.project.projectFile, activity); } let result = true; for (let file of this.project.files) { if (file.fileType.toLowerCase() == activity.sourceExtension) { result = await this.buildTarget(file, activity) && result; } } return result; } async buildTarget(file, activity) { const options = { ...this.options }; const outfile = this.project.resolveOutputFilePath(file, activity.sourceExtension, activity.compiledExtension); options.checkFilenameConventions = this.project.options.checkFilenameConventions ?? this.options.checkFilenameConventions; const infile = this.project.resolveInputFilePath(file); const buildFilename = path.relative(process.cwd(), infile).replace(/\\/g, '/'); const callbacks = new CompilerFileCallbacks(buildFilename, options, this.callbacks); callbacks.reportMessage(InfrastructureMessages.Info_BuildingFile({ filename: infile, relativeFilename: buildFilename })); fs.mkdirSync(path.dirname(outfile), { recursive: true }); let result = await activity.build(infile, outfile, callbacks, options); // check if we had a message that causes the build to be a failure // note: command line option here, if set, overrides project setting result = result && !callbacks.hasFailureMessage(this.options.compilerWarningsAsErrors ?? this.project.options.compilerWarningsAsErrors); if (result) { callbacks.reportMessage(InfrastructureMessages.Info_FileBuiltSuccessfully({ filename: infile, relativeFilename: buildFilename })); } else { callbacks.reportMessage(InfrastructureMessages.Info_FileNotBuiltSuccessfully({ filename: infile, relativeFilename: buildFilename })); } return result; } } //# sourceMappingURL=BuildProject.js.map