egret 引擎分析之二————从selector.js说起

前面说了,在控制台执行egret命令其实就是node   /Applications/EgretLauncher.app/Contents/Resources/app/engine/mac/selector.js

所以selector.js里面的js代码就是他做的事情。

  1 /*
  2 
  3  此文件需要放在引擎安装目录
  4  例如 C:Program FilesEgretEgretEnginewinselector.js
  5  或   /Applications/EgretEngine.app/Contents/Resources/mac/selector.js
  6 
  7  根据命令行参数
  8  --ev 2.4.3
  9  或项目中 egretProperties.json 中指定的引擎版本来执行对应的引擎。
 10 
 11  引擎选择优先级为
 12  --ev
 13  egretProperties.json
 14  默认引擎
 15 
 16 
 17  历史版本的引擎位置为:
 18  Mac: /Users/${user}/Library/Application Support/Egret/engine/${version}/
 19  Windows: %AppData%/Egret/engine/${version}/
 20  其中根目录下有 config.json(可选,默认没有) 记录默认引擎和自定义引擎目录
 21  {
 22  "egret":{
 23  "2.0.5":{
 24  "root":"D:\Work\egret-core\" //自定义目录
 25  },
 26  "defaultEngine":"2.4.3"
 27  }
 28  }
 29 
 30 
 31  默认版本查找顺序
 32  config.json defaultEngine 指定的版本号
 33  config.json 中指定的自定义路径
 34  引擎安装目录/egret
 35  历史版本根目录/${version}
 36  EGRET_PATH环境变量仅仅作为兼容以前版本使用
 37 
 38 
 39 
 40  egret versions 命令输出可用的引擎版本
 41  Egret Engine 2.4.3  D:/Program Files/Egret/EgretEngine/win/egret/
 42  Egret Engine 2.0.5  D:/Work/egret-core/
 43 
 44 
 45  */
 46 var FS = require("fs");
 47 var Path = require("path");
 48 var selector = require('../egret').selector;
 49 var stat = require('../../stat/egretStat');
 50 var DEFAULT_ENGINE = "defaultEngine";
 51 var args;
 52 var osLocal = require("../os-local.js");
 53 var i18n = osLocal();
 54 i18n = i18n.toLowerCase();
 55 if (i18n == "zh_cn" || i18n == "zh_tw" || i18n == "zh_hk") {
 56     var language = 'zh';
 57 } else {
 58     language = 'en'
 59 }
 60 
 61 var engines;
 62 var localsMessages = {
 63     en: {
 64         1: "Can not find Egret Engine {0}, please install it with Egret Launcher.",
 65         2: "Can not find Egret Engine, please open Egret Launcher and install.",
 66         3: "Egret Engine latest version: {0}
Egret Engine current version: {1}
You can upgrade your project via egret upgrade",
 67         4: "Egret Engine latest version: {0}",
 68         5: "Error! The egretProperties.json is not a valid json.",
 69         6: "egret upgrade Need to specify version
usage: egret upgrade --egretversion [target version]
Current upgradeable version:",
 70         7: "Error! The egretProperties.json have no egret_version.",
 71         8: "The specified version number must be greater than the version number of the current project, current project version {0}",
 72         9: "The current project version is already {0}.",
 73         10: "current project version",
 74         11: "egret make Need to specify version
usage: egret make --egretversion [target version]"
 75     },
 76     zh: {
 77         1: "未找到 Egret Engine {0} ,请在Egret Launcher中安装该版本引擎",
 78         2: "尚未安装引擎,请在Egret Launcher中安装该版本引擎",
 79         3: "您安装的最新引擎版本为 {0}
当前项目使用版本为 {1}
您可以执行 egret upgrade 命令升级项目",
 80         4: "您安装的最新引擎版本为 {0}",
 81         5: "错误!! egretProperties.json 不是有效的 json 文件",
 82         6: "egret upgrade 需要指定升级版本
usage: egret upgrade --egretversion [target version]
当前可升级版本号:",
 83         7: "错误!! egretProperties.json 没有有效的 egret_version",
 84         8: "指定的版本号必须大于当前项目的版本号,当前项目版本{0}",
 85         9: "当前项目版本已是{0},无需升级",
 86         10: "当前项目版本",
 87         11: "egret make 需要指定引擎版本
usage: egret make --egretversion [target version]"
 88     }
 89 };
 90 var commandsToSkip = {
 91     "upgrade": true
 92 };
 93 function entry() {
 94     engines = selector.getAllEngineVersions();
 95     args = parseArgs();
 96     var requestVersion = args.egretversion || args.ev;
 97     if (requestVersion === true)
 98         requestVersion = undefined;
 99     var handled = false;
100     let statArgs = process.argv.concat();
101     statArgs.splice(0, 2);
102     var statData = {
103         command: args.command,
104         parameters: statArgs.join(' '),
105         path: process.cwd(),
106         source: process.title
107     };
108     let userName = selector.getUserName();
109     if (args.command === "versions") {
110         handled = true;
111         printVersions();
112     }
113     if(args.command === "paths"){
114         handled = true;
115         printTools();
116     }
117     if(handled){
118         stat.egretStat("cmd", userName, statData);
119         return;
120     }
121     var projectVersion = getProjectVersion();
122     statData["egretversion"] = projectVersion;
123     stat.egretStat("cmd", userName, statData);
124     var projectVersion = getProjectVersion();
125     var latestVersion = selector.chooseLatestEngine();
126     if (!latestVersion) {
127         console.log(tr(2));
128         process.exit(2);
129         return;
130     }
131     if (args.command === "make") {
132         if (!requestVersion) {
133             console.log(tr(11));
134             return;
135         }
136     }
137     if (args.command == "upgrade") {
138         if (!projectVersion) {
139             console.log(tr(7));
140             return;
141         }
142         if (!requestVersion) {
143             let upgradeableEngines = [];
144             if (projectVersion) {
145                 Object.keys(engines).sort(compareVersion).reverse().forEach(function (v) {
146                     let value = compareVersion(engines[v].version, projectVersion);
147                     if (value > 0) {
148                         upgradeableEngines.push(engines[v].version);
149                     } else if (value === 0) {
150                         upgradeableEngines.push(engines[v].version + " [" + tr(10) + "]");
151                     }
152                 });
153             }
154             console.log(tr(6));
155             upgradeableEngines.forEach(function (e) {
156                 console.log(e);
157             });
158             return;
159         }
160         if (compareVersion(requestVersion, projectVersion) < 0) {
161             console.log(tr(8, projectVersion));
162             return;
163         }
164         if (compareVersion(requestVersion, projectVersion) == 0) {
165             console.log(tr(9, projectVersion));
166             return;
167         }
168     }
169     if (requestVersion || (projectVersion && !(args.command in commandsToSkip))) {
170         requestVersion = requestVersion || projectVersion;
171         if (!engines[requestVersion]) {
172             console.log(tr(1, requestVersion));
173             process.exit(1);
174             return;
175         }
176         if (projectVersion && !(args.command in commandsToSkip) && compareVersion(projectVersion, latestVersion.version) < 0) {
177             console.log(tr(3, latestVersion.version, projectVersion));
178         }
179         executeVersion(requestVersion);
180         return;
181     }
182     if (!handled) {
183         executeVersion(latestVersion.version, latestVersion.root);
184     }
185 }
186 function printVersions() {
187     if (!engines) {
188         getAllEngineVersions();
189     }
190     Object.keys(engines).sort(compareVersion).reverse().forEach(function (v) {
191         console.log(("Egret Engine " + engines[v].version + "  ") + engines[v].root);
192     });
193 }
194 function printTools() {
195     let tools = selector.getInstalledTools();
196     console.log(JSON.stringify(tools, null, "    "));
197 }
198 function executeVersion(version, root) {
199     root = root || engines[version].root;
200     var bin = selector.getBin(root);
201     process.env["EGRET_PATH"] = root;
202     //Fix 1.5 can not find typescript lib
203     if (process['mainModule']) {
204         process['mainModule'].filename = bin;
205     }
206     require(bin);
207     return true;
208 }
209 
210 function getProjectVersion() {
211     var dir;
212     if (args.command != "create_app") {
213         dir = args.projectDir;
214     }
215     else {
216         dir = args["f"];
217     }
218     var propsPath = file.joinPath(dir, "egretProperties.json");
219     if(!file.exists(propsPath)){
220         propsPath = file.joinPath(dir, "package.json");
221     }
222     if (file.exists(propsPath)) {
223         var jsonText = file.read(propsPath);
224         var props;
225         try {
226             props = JSON.parse(jsonText);
227         }
228         catch (e) {
229             console.log(tr(5));
230             process.exit(2);
231         }
232         if (props["compilerVersion"]) {
233             return props["compilerVersion"];
234         }
235         if (props["egret_version"]) {
236             return props["egret_version"];
237         }
238         return props["version"];
239     }
240     return null;
241 }
242 
243 function tr(code) {
244     var args = [];
245     for (var _i = 1; _i < arguments.length; _i++) {
246         args[_i - 1] = arguments[_i];
247     }
248     var messages = localsMessages[language];
249     var message = messages[code];
250     message = format(message, args);
251     return message;
252 }
253 function format(text, args) {
254     var length = args.length;
255     for (var i = 0; i < length; i++) {
256         text = text.replace(new RegExp("\{" + i + "\}", "ig"), args[i]);
257     }
258     return text;
259 }
260 function parseArgs() {
261     var i = 0;
262     var commands = [];
263     var options = {};
264     var args = process.argv.concat();
265     args.splice(0, 2);
266     while (i < args.length) {
267         var s = args[i++];
268         if (s.charAt(0) === '-') {
269             s = s.slice(s.charAt(1) === '-' ? 2 : 1).toLowerCase();
270             if (!args[i] || args[i].charAt(0) == '-') {
271                 options[s] = true;
272             }
273             else {
274                 options[s] = args[i++] || "";
275             }
276         }
277         else {
278             commands.push(s);
279         }
280     }
281     if (commands.length > 0) {
282         options.command = commands[0];
283         if (commands.length > 1 && file.isDirectory(commands[1])) {
284             options.projectDir = commands[1];
285         }
286     }
287     if (options.projectDir == null) {
288         options.projectDir = process.cwd();
289     }
290     else {
291         var absPath = file.joinPath(process.cwd(), options.projectDir);
292         if (file.isDirectory(absPath)) {
293             options.projectDir = absPath;
294         }
295     }
296     options.projectDir = file.joinPath(options.projectDir, "/");
297     return options;
298 }
299 function compareVersion(v1, v2) {
300     return versionToNumber(v1) - versionToNumber(v2);
301     function versionToNumber(v) {
302         var numbers = v.split(".").map(function (n) {
303             try {
304                 return parseInt(n) || 0;
305             }
306             catch (e) {
307                 return 0;
308             }
309         });
310         var total = 0;
311         numbers.forEach(function (n, i) {
312             total += n * Math.pow(0.01, i);
313         });
314         return total;
315     }
316 }
317 var file;
318 (function (file) {
319     var charset = "utf-8";
320     /**
321      * 指定路径的文件或文件夹是否存在
322      */
323     function exists(path) {
324         path = escapePath(path);
325         return FS.existsSync(path);
326     }
327     file.exists = exists;
328     /**
329      * 转换本机路径为Unix风格路径。
330      */
331     function escapePath(path) {
332         if (!path)
333             return "";
334         return path.split("\").join("/");
335     }
336     file.escapePath = escapePath;
337     /**
338      * 读取文本文件,返回打开文本的字符串内容,若失败,返回"".
339      * @param path 要打开的文件路径
340      */
341     function read(path, ignoreCache) {
342         if (ignoreCache === void 0) { ignoreCache = false; }
343         path = escapePath(path);
344         try {
345             var text = FS.readFileSync(path, charset);
346             text = text.replace(/^uFEFF/, '');
347         }
348         catch (err0) {
349             return "";
350         }
351         return text;
352     }
353     file.read = read;
354     /**
355      * 连接路径,支持传入多于两个的参数。也支持"../"相对路径解析。返回的分隔符为Unix风格。
356      */
357     function joinPath(dir) {
358         var filename = [];
359         for (var _i = 1; _i < arguments.length; _i++) {
360             filename[_i - 1] = arguments[_i];
361         }
362         var path = Path.join.apply(null, arguments);
363         path = escapePath(path);
364         return path;
365     }
366     file.joinPath = joinPath;
367     function isDirectory(path) {
368         path = escapePath(path);
369         try {
370             var stat = FS.statSync(path);
371         }
372         catch (e) {
373             return false;
374         }
375         return stat.isDirectory();
376     }
377     file.isDirectory = isDirectory;
378     /**
379      * 获取指定文件夹下的文件或文件夹列表,不包含子文件夹内的文件。
380      * @param path 要搜索的文件夹
381      * @param relative 是否返回相对路径,若不传入或传入false,都返回绝对路径。
382      */
383     function getDirectoryListing(path, relative) {
384         if (relative === void 0) { relative = false; }
385         path = escapePath(path);
386         try {
387             var list = FS.readdirSync(path);
388         }
389         catch (e) {
390             return [];
391         }
392         var length = list.length;
393         if (!relative) {
394             for (var i = length - 1; i >= 0; i--) {
395                 if (list[i].charAt(0) == ".") {
396                     list.splice(i, 1);
397                 }
398                 else {
399                     list[i] = joinPath(path, list[i]);
400                 }
401             }
402         }
403         else {
404             for (i = length - 1; i >= 0; i--) {
405                 if (list[i].charAt(0) == ".") {
406                     list.splice(i, 1);
407                 }
408             }
409         }
410         return list;
411     }
412     file.getDirectoryListing = getDirectoryListing;
413     /**
414      * 获取路径的文件名(不含扩展名)或文件夹名
415      */
416     function getFileName(path) {
417         if (!path)
418             return "";
419         path = escapePath(path);
420         var startIndex = path.lastIndexOf("/");
421         var endIndex;
422         if (startIndex > 0 && startIndex == path.length - 1) {
423             path = path.substring(0, path.length - 1);
424             startIndex = path.lastIndexOf("/");
425             endIndex = path.length;
426             return path.substring(startIndex + 1, endIndex);
427         }
428         endIndex = path.lastIndexOf(".");
429         if (endIndex == -1 || isDirectory(path))
430             endIndex = path.length;
431         return path.substring(startIndex + 1, endIndex);
432     }
433     file.getFileName = getFileName;
434 })(file || (file = {}));
435 function getLanguage() {
436     var selector = process['mainModule'].filename;
437     var languageXML = file.escapePath(file.joinPath(Path.dirname(selector), '../locales/language.xml'));
438     if (file.exists(languageXML)) {
439         var xml = file.read(languageXML);
440         var lang = /<language>([w_]*)</language>/.exec(xml);
441         if (lang) {
442             var localParts = lang[1].split('_');
443             if (localParts.length >= 1) {
444                 language = localParts[0];
445             }
446         }
447     }
448     if (!language || language != "zh") {
449         language = "en";
450     }
451 }
452 entry();
View Code

 这个里面其他都不用关心,最后就是到了executeVersion函数里面。

 就是require(bin);//bin:/Users/UserName/Library/Application Support/Egret/engine/5.3.7/tools/bin/egret

而这个就是egret就是引擎下面的egret文件,

我们进去看,其实就一句话:

require('../Entry.js').executeCommandLine(process.argv.slice(2))

即包含了../Entry.js,然后执行返回对象的executeCommandLine(process.argv.slice(2))。

这就真的进入了引擎的Entry.js文件,执行执行命令行函数了。

所以就是从这里进入了引擎代码里面了,接下来就去看引擎代码就好啦。

原文地址:https://www.cnblogs.com/hackerl/p/13541884.html