[记录点滴]Ionic编译过程的研究
[记录点滴]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编译过程的研究的更多相关文章
- CUDA 编程相关;tensorflow GPU 编程;关键知识点记录;CUDA 编译过程;NVCC
本文章主要是记录,cuda 编程过程中遇到的相关概念,名字解释和问题:主要是是用来备忘: cuda PTX :并行线程执行(Parallel Thread eXecution,PTX)代码是编译后的G ...
- 记录下MoKee编译过程
纯属记录帖 关注和了解这个rom有段时间了. 最近有需要了解odex,折腾了几天还是在坑里. 索性,先编译下MoKee看看. 之前make过 4.2 和 5.1 ,刷到模拟器和N5里. 编译教程可以参 ...
- OpenSift源代码编译过程记录
本文记录了在CentOS6.5上编译Sift的开源实现OpenSift的编译过程,同一时候记录了编译过程中的几个问题. sift的理论已经有非常多了,以下会给出链接: 1.Requirements a ...
- 记录在Python2.7 x64 bit 下 PyQt5.8的编译过程
由于工作需要使用python下面的Qt库.PyQt现在只提供针对Python3.X系列的PyQt,所有需要自己手动编译.防止忘记,特意写下随笔记录备忘. 工 作 环境:Python版本:Python ...
- win10--vs2015--libjpeg--64位库的编译过程记录
win10--vs2015--libjpeg--64位库的编译过程记录 1. 下载源代码: http://libjpeg.sourceforge.net/ 或者 http://www.ij ...
- Latex — 写作编译过程中遇到问题记录与总结
最近在训练的时候,又开始用Latex进行写作.碰到了很多问题,将问题进行记录与总结. 一.输出中文的问题 由于写作的时候用的是中文,而之前用的是英文,故碰到的第一个问题就是中文的问题.我之前下的是Wi ...
- live555源码研究(十)------在编译过程中遇到的问题及解决方法
一.编译testOnDemandRTSPServer.cpp. 在testProgs项目中,加入testOnDemandRTSPServer.cpp进行编译,编译类型是编译成exe文件,在编译过程中会 ...
- C语言编译过程(转)
内容摘要 : C语言编译的整个过程是非常复杂的,里面涉及到的编译器知识.硬件知识.工具链知识都是非常多的,深入了解整个编译过程对工程师理解应用程序的编写是有很大帮助的,希望大家可以多了解一些,在遇到问 ...
- Android安装包相关知识汇总 (编译过程图给力)
转自: https://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=208008519&idx=1&sn=278b7793699 ...
- 第48章 MDK的编译过程及文件类型全解—零死角玩转STM32-F429系列
第48章 MDK的编译过程及文件类型全解 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
随机推荐
- java——棋牌类游戏五子棋(singlewzq1.0)之一
这是本人最近一段时间写的五子棋的java代码,大体框架都实现了,一些细节还需要优化. package basegame; import java.awt.Color; import java.awt. ...
- Python:pygame游戏编程之旅四(游戏界面文字处理)
本节讲解游戏界面中字体的处理,以在界面中实时显示当前时间.小球位置为例进行实验,具体见代码. 一.代码 # -*- coding:utf-8 -*- import os import sys impo ...
- python之高级数据结构Collections
1. Collections collections模块包含了内建类型之外的一些有用的工具,例如Counter.defaultdict.OrderedDict.deque以及nametuple.其中C ...
- git 本地项目与远程地址建立连接
git 本地项目与远程地址建立连接 建立好远程仓库与本地项目地址后 在本地项目文件夹内初始化git仓库 git init 复制远程项目路径地址,后执行: git remote add origin 远 ...
- COSBrowser 移动端——随时随地查看管理数据
外出身边没有电脑,需要查看管理数据怎么办? 出现紧急情况,需要快速停止某个 bucket 对外访问,怎么办? 个人用户仅作为网盘使用,需要方便轻量的管理工具,怎么办? 不用着急,COSBrowser ...
- 【MyBatis】学习笔记09:动态设置表名
[Mybatis]学习笔记01:连接数据库,实现增删改 [Mybatis]学习笔记02:实现简单的查 [MyBatis]学习笔记03:配置文件进一步解读(非常重要) [MyBatis]学习笔记04:配 ...
- Web前端常见的英文缩写
PV (Page View)页面浏览量 FED(Front-End Development)前端开发 F2E(Front-End Engineer)前端工程师 WWW(World Wide Web)万 ...
- Vue3封装一个ElementPlus自定义上传组件2--无弹窗
Vue3封装一个ElementPlus自定义上传组件2--无弹窗 写在前面: 无弹窗的上传组件它来了,依旧是小巧又好用,只不过这回我用的是前端直传的方式,采用http-request进行文件上传,中间 ...
- Qt编写安防视频监控系统45-图文报表
一.前言 图文报表对应以前的文字报表,以前的日志查询后,需要打印或者导出,都是一行行的文字记录,近期需要图文警情记录打印和导出,于是彻底趁机将之前的数据导入导出(xls/pdf)及打印组件彻底改造重写 ...
- Qt音视频开发46-视频传输UDP版
一.前言 上篇文章写道采用的TCP传输视频,优缺点很明显,优点就是不丢包,缺点就是速度慢,后面换成UDP通信,速度快了很多,少了3次握手,而且在局域网中基本上不丢包,就算偶尔丢包,对于一秒钟25-30 ...