[記録点滴]Ionicコンパイルプロセスの研究
10232 ワード
[記録点滴]Ionicコンパイルプロセスの研究
0 x 00サマリ
以前、Ionicのコンパイルプロセスを研究していたノートを、記録に出しました.当時、一部の画像がアプリケーションにコピーされていなかったため、コンパイルプロセスをデバッグする必要があった.
0 x 01エントリ
コンパイルされたエントリはplatformsandroidcordovaで、具体的には次のスクリプトファイルです.
対応するコマンドはionic run/build/clean...
0 x 02実行
runを例にとると、buildの下のrun関数platformsandroidcordovalibrunが呼び出されます.js
buildを例にとるとbuild.batはbuildファイルを直接呼び出し、コンパイルします.
実際に実行
buildが本当に実行するコマンドはここにあります.
Apiでjsではbuildコードは次のとおりです.
Check
cordovalibの下のコード
ビルダーの選択
cordovalibbuildersの下の関数はantやgradleなどの特定のbuilderを呼び出します.
platforms\android\cordova\lib\builders\builder.jsは具体的にどんなbuilderを選びますか.
GradleBuilder
Gradleのコンパイルコールは
0 x 03コピーファイルの照合
キーワードの検索
最初のステップは、ファイルのコピーが正しいかどうかを見て、初歩的な疑いはここにあります.ここはjsファイルばかりなのでconsole.log()などの関数はlogを印刷し、コンパイルプロセスをファイルに入力して見ます.例えばionic build android>logです.txt,コマンド実行が完了したらlogを見る.txtファイルのlog
ステップ2では、logコードを実験的に追加します.
3つ目はlogを見てみましょう
0 x 00サマリ
以前、Ionicのコンパイルプロセスを研究していたノートを、記録に出しました.当時、一部の画像がアプリケーションにコピーされていなかったため、コンパイルプロセスをデバッグする必要があった.
0 x 01エントリ
コンパイルされたエントリはplatformsandroidcordovaで、具体的には次のスクリプトファイルです.
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...
0 x 02実行
runを例にとると、buildの下のrun関数platformsandroidcordovalibrunが呼び出されます.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
cordovalibの下のコード
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
];
}
ビルダーの選択
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):
\t' + apkPaths.join('
\t'));
return {
apkPaths: apkPaths,
buildType: opts.buildType,
buildMethod: opts.buildMethod
};
});
});
};
cordovalibbuildersの下の関数はantやgradleなどの特定のbuilderを呼び出します.
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);
});
};
0 x 03コピーファイルの照合
キーワードの検索
{ 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');
});
};
ステップ2では、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);
....
}
3つ目は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
odejs
ode.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