[记录点滴]Ionic编译过程的研究

0x00 摘要

之前研究Ionic编译过程的笔记,发出来做个记录。当时是因为有些图片没有拷贝到应用中,所以需要调试编译过程。

0x01 入口

编译的入口在platforms\android\cordova,具体是以下脚本文件:

android_sdk_version  build.bat       clean         lib      loggingHelper.js  run.bat
Api.js check_reqs clean.bat log node_modules version
build check_reqs.bat defaults.xml log.bat run version.bat

对应的命令就是ionic run/build/clean...

0x02 执行

以run为例,其会调用build下面的run函数 platforms\android\cordova\lib\run.js

build = require('./build'),

module.exports.run = function(runOptions) {
return Q()
...
return build.run.call(self, runOptions, resolvedTarget)
...
}
};

以build为例,build.bat会直接调用build文件,进行编译。

真正执行

build真正执行的命令在这里:

new Api().build(buildOpts)

./android/cordova/Api.js:Api.prototype.prepare = function (cordovaProject, prepareOptions) {
./android/cordova/Api.js: return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions);
./android/cordova/Api.js: return require('./lib/prepare').clean.call(self, cleanOptions);

在Api.js中,build代码如下:

Api.prototype.build = function (buildOptions) {
var self = this;
return require('./lib/check_reqs').run()
.then(function () {
return require('./lib/build').run.call(self, buildOptions);
})
.then(function (buildResults) {
// Cast build result to array of build artifacts
return buildResults.apkPaths.map(function (apkPath) {
return {
buildType: buildResults.buildType,
buildMethod: buildResults.buildMethod,
path: apkPath,
type: 'apk'
};
});
});
};

Check

cordova\lib下面的代码 platforms\android\cordova\lib\check_reqs.js 做了各种check。

module.exports.check_all = function() {
var requirements = [
new Requirement('java', 'Java JDK'),
new Requirement('androidSdk', 'Android SDK'),
new Requirement('androidTarget', 'Android target'),
new Requirement('gradle', 'Gradle')
]; var checkFns = [
this.check_java,
this.check_android,
this.check_android_target,
this.check_gradle
];
}

选择builder

platforms\android\cordova\lib\build.js 会选择一个builder,然后调用其的build函数

var builders = require('./builders/builders');

module.exports.run = function(options, optResolvedTarget) {
var opts = parseOpts(options, optResolvedTarget, this.root);
var builder = builders.getBuilder(opts.buildMethod);
return builder.prepEnv(opts)
.then(function() {
if (opts.prepEnv) {
events.emit('verbose', 'Build file successfully prepared.');
return;
}
return builder.build(opts)
.then(function() {
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
return {
apkPaths: apkPaths,
buildType: opts.buildType,
buildMethod: opts.buildMethod
};
});
});
};

cordova\lib\builders下面的函数 会调用具体的builder,比如ant还是gradle。

platforms\android\cordova\lib\builders\builder.js 具体做选什么builder。

var knownBuilders = {
ant: 'AntBuilder',
gradle: 'GradleBuilder',
none: 'GenericBuilder'
}; module.exports.getBuilder = function (builderType, projectRoot) {
if (!knownBuilders[builderType])
throw new CordovaError('Builder ' + builderType + ' is not supported.');
try {
var Builder = require('./' + knownBuilders[builderType]);
return new Builder(projectRoot);
} catch (err) {
throw new CordovaError('Failed to instantiate ' + knownBuilders[builderType] + ' builder: ' + err);
}
};

GradleBuilder

Gradle的编译调用在 platforms\android\cordova\lib\builders\GradleBuilder.js

GradleBuilder.prototype.build = function(opts) {
var wrapper = path.join(this.root, 'gradlew');
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts); return spawn(wrapper, args, {stdio: 'pipe'})
.progress(function (stdio){
if (stdio.stderr) {
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
if (suppressThisLine) {
return;
}
process.stderr.write(stdio.stderr);
} else {
process.stdout.write(stdio.stdout);
}
}).catch(function (error) {
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
return check_reqs.check_android_target(error).then(function() {
// If due to some odd reason - check_android_target succeeds
// we should still fail here.
return Q.reject(error);
});
}
return Q.reject(error);
});
};

0x03 排查拷贝文件

关键词的查找

{ platforms }  ? find -type f | xargs grep -w "shell.cp"
./android/cordova/lib/builders/GradleBuilder.js: shell.cp('-f', pluginBuildGradle, path.join(this.root, subProjects[i], 'build.gradle'));
./android/cordova/lib/builders/GradleBuilder.js: shell.cp(path.join(wrapperDir, 'gradlew.bat'), self.root);
./android/cordova/lib/builders/GradleBuilder.js: shell.cp(path.join(wrapperDir, 'gradlew'), self.root);
./android/cordova/lib/builders/GradleBuilder.js: shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(self.root, 'gradle'));
./android/cordova/lib/pluginHandlers.js: shell.cp('-Rf', src+'/*', dest);
./android/cordova/lib/pluginHandlers.js: shell.cp('-f', src, dest);
./android/cordova/lib/prepare.js: shell.cp('-f', locations.defaultConfigXml, locations.configXml);
./android/cordova/node_modules/cordova-common/src/FileUpdater.js: shell.cp("-f", sourceFullPath, targetFullPath);
./android/cordova/node_modules/cordova-common/src/FileUpdater.js: shell.cp("-f", sourceFullPath, targetFullPath);
./android/cordova/node_modules/cordova-common/src/FileUpdater.js: shell.cp("-f", sourceFullPath, targetFullPath);
{ platforms }  ? find -type f | xargs grep -w mergeAndUpdateDir
./android/cordova/lib/prepare.js: FileUpdater.mergeAndUpdateDir(
./android/cordova/lib/prepare.js: // No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
./android/cordova/lib/prepare.js: FileUpdater.mergeAndUpdateDir(
./android/cordova/node_modules/cordova-common/src/FileUpdater.js:function mergeAndUpdateDir(sourceDirs, targetDir, options, log) {
./android/cordova/node_modules/cordova-common/src/FileUpdater.js: mergeAndUpdateDir: mergeAndUpdateDir

第一步,看看是否拷贝文件正确,初步怀疑是在这里。因为这里都是js文件,所以可以用console.log()等函数打印log, 然后把编译过程输入到文件中看,比如ionic build android > log.txt, 命令执行结束之后,看log.txt文件中的log

./android/cordova/lib/prepare.js

module.exports.prepare = function (cordovaProject, options) {
var self = this;
var platformResourcesDir = path.relative(cordovaProject.root, path.join(this.locations.root, 'res')); -------- 打印platformResourcesDir,看看这个数据是否正确 // Update own www dir with project's www assets and plugins' assets and js-files
return Q.when(updateWww(cordovaProject, this.locations))
.then(function () {
// update project according to config.xml changes.
return updateProjectAccordingTo(self._config, self.locations);
})
.then(function () { ------------- 在这里更新图标和启动界面的,所以以图标为例,看看updateIcons是否拷贝成功 updateIcons(cordovaProject, platformResourcesDir);
updateSplashes(cordovaProject, platformResourcesDir);
})
.then(function () {
events.emit('verbose', 'Prepared android project successfully');
});
};

第二步,实验添加log代码:

cordova\lib\run.js
module.exports.run = function(runOptions) {
console.log("================= cordova lib run =================");
} cordova\lib\prepare.js
module.exports.prepare = function (cordovaProject) {
console.log("================= cordova lib prepare =================");
.....
var projectRoot = path.dirname(projectConfig.path);
var destination = path.join(platformRoot, 'res');
console.log("================= cordova lib handleIcons =================projectRoot: " + projectRoot);
console.log("================= cordova lib prepare =================destination: " + destination);
....
}

第三步,执行看看log

C:\>ionic prepare android
================= cordova lib prepare =================
================= cordova lib handleIcons =================projectRoot: C
================= cordova lib prepare =================destination: C:\platforms\android\res
Running command: "C:\Program Files\nodejs\node.exe"
add to body class: platform-android
will push strings array {"name":"lang","titles":["English (US)","English (UK)"],
"values":["en-us","en-gb"]}
android preferences file was successfully generated
C:\>ionic build android
================= cordova lib prepare =================
================= cordova lib handleIcons =================projectRoot:
BUILD SUCCESSFUL
Total time: 19.631 secs

[记录点滴]Ionic编译过程的研究的更多相关文章

  1. CUDA 编程相关;tensorflow GPU 编程;关键知识点记录;CUDA 编译过程;NVCC

    本文章主要是记录,cuda 编程过程中遇到的相关概念,名字解释和问题:主要是是用来备忘: cuda PTX :并行线程执行(Parallel Thread eXecution,PTX)代码是编译后的G ...

  2. 记录下MoKee编译过程

    纯属记录帖 关注和了解这个rom有段时间了. 最近有需要了解odex,折腾了几天还是在坑里. 索性,先编译下MoKee看看. 之前make过 4.2 和 5.1 ,刷到模拟器和N5里. 编译教程可以参 ...

  3. OpenSift源代码编译过程记录

    本文记录了在CentOS6.5上编译Sift的开源实现OpenSift的编译过程,同一时候记录了编译过程中的几个问题. sift的理论已经有非常多了,以下会给出链接: 1.Requirements a ...

  4. 记录在Python2.7 x64 bit 下 PyQt5.8的编译过程

    由于工作需要使用python下面的Qt库.PyQt现在只提供针对Python3.X系列的PyQt,所有需要自己手动编译.防止忘记,特意写下随笔记录备忘. 工 作  环境:Python版本:Python ...

  5. win10--vs2015--libjpeg--64位库的编译过程记录

    win10--vs2015--libjpeg--64位库的编译过程记录 1. 下载源代码:   http://libjpeg.sourceforge.net/    或者  http://www.ij ...

  6. Latex — 写作编译过程中遇到问题记录与总结

    最近在训练的时候,又开始用Latex进行写作.碰到了很多问题,将问题进行记录与总结. 一.输出中文的问题 由于写作的时候用的是中文,而之前用的是英文,故碰到的第一个问题就是中文的问题.我之前下的是Wi ...

  7. live555源码研究(十)------在编译过程中遇到的问题及解决方法

    一.编译testOnDemandRTSPServer.cpp. 在testProgs项目中,加入testOnDemandRTSPServer.cpp进行编译,编译类型是编译成exe文件,在编译过程中会 ...

  8. C语言编译过程(转)

    内容摘要 : C语言编译的整个过程是非常复杂的,里面涉及到的编译器知识.硬件知识.工具链知识都是非常多的,深入了解整个编译过程对工程师理解应用程序的编写是有很大帮助的,希望大家可以多了解一些,在遇到问 ...

  9. Android安装包相关知识汇总 (编译过程图给力)

    转自: https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208008519&idx=1&sn=278b7793699 ...

  10. 第48章 MDK的编译过程及文件类型全解—零死角玩转STM32-F429系列

    第48章     MDK的编译过程及文件类型全解 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...

随机推荐

  1. 读书笔记-C#8.0本质论-05

    18.3 基于任务的异步编程模式 18.3.1 使用任务并行库(TPL)实现异步执行高延迟操作 using System; using System.Net.Http; using System.Th ...

  2. Java 并发编程实战学习笔记——路径查找类型并行任务的终止

    1.该类问题的递归串行算法(深度优先遍历) 代码 复制 - 运行 package net.jcip.examples; import java.util.*; /** * SequentialPuzz ...

  3. Python3.6,3.7,3.8版本对比

    本文列举了Python3.6.3.7.3.8三个版本的新特性,学习它们有助于提高对Python的了解,跟上最新的潮流. 一.Python3.6新特性 1.新的格式化字符串方式 新的格式化字符串方式,即 ...

  4. Vue日常使用与常见问题

    使用: 1.在使用elementUI自定义表格中字段样式 官方文档:https://element.eleme.cn/2.10/#/zh-CN/component/table # 基础使用 <t ...

  5. Codeforces Round #826 (Div

    Codeforces Round #826 (Div. 3) Minimize the Thickness 给定数组a,要求将数组a分成若干个子序列,并且使得每个子序列中的元素和都相等,设这些子序列中 ...

  6. Coqui TTS合成语音

    工具介绍 Coqui TTS是一个用于语音转文本的高性能深度学习模型库.提供1100种语言的预训练模型,提供训练新模型和微调已有模型的工具,提供数据集分析工具.XTTS-v2版本支持16种语言: En ...

  7. H5 新增表单

    1.提示占位 placeholder <input type="text" name="userName" placeholder="请输入用户 ...

  8. 远程连接利器:玩转MobaXterm

    今天这篇文章轻松不烧脑,主要是想和大家分享一下我在工作中常用的远程管理工具--MobaXterm.这款工具不仅功能强大,而且在日常的远程操作中极为高效,特别适合用来管理远程服务器.MobaXterm结 ...

  9. 获取Map中选择的要素

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  10. 对象存储 COS 推出一站式内容审核服务,助力打造绿色互联网

    今年,国家网信办深入推进"清朗·春节网络环境"专项行动.截至3月24日,网信办共累计清理相关违法违规信息208万余条,处置账号7.2万余个,协调关闭.取消备案网站平台2300余家. ...