Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-24734] Add compatibility with Hyperloop AAR handling #9086

Merged
merged 5 commits into from
Jul 6, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
102 changes: 101 additions & 1 deletion android/cli/hooks/aar-transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ const LIBRARY_ORIGIN_PORJECT = 'Project';

exports.cliVersion = '>=3.2';

exports.init = function (logger, config, cli) {
exports.init = function (logger, config, cli, appc) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The varying argument order for the same objects bugs me:
(logger, config, cli, appc) vs
(cli, builder, appc, logger) vs
(builder, callback) vs
(builder, logger, callback)

I prefer to try and retain argument order relatively if possible, so I guess in these cases it would be:
(logger, config, cli, appc, callback) - where builder falls, I'm not sure beyond having it before callback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sorted the arguments a little bit by their priority. cli and builder being the main objects i interact with, followed by utility stuff like appc and logger and the callback always being the last argument.

cli.on('build.pre.compile', {
priority: 1100,
post: function(builder, callback) {
registerHyperloopCompatibilityFixes(cli, builder, appc, logger);
scanProjectAndStartTransform(builder, logger, callback);
}
});
Expand Down Expand Up @@ -445,3 +446,102 @@ class SimpleFileCache {
fs.writeFileSync(this.cachePathAndFilename, dataToWrite);
}
}

/**
* Hyperloop versions below 2.2.0 have their own AAR handling which we need to
* disable by hooking into the affected hooks and reverting the changes Hyperloop
* made.
*
* @param {Object} cli CLI instance
* @param {Object} builder Builder instance
* @param {Object} appc Appc node utilities
* @param {Object} logger Logger instance
*/
function registerHyperloopCompatibilityFixes(cli, builder, appc, logger) {
var hyperloopModule = null;
builder.nativeLibModules.some(function (module) {
if (module.id === 'hyperloop' && appc.version.lt(module.version, '2.2.0')) {
hyperloopModule = module;
return true;
}
});
if (hyperloopModule === null) {
return;
}

var hyperloopBuildPath = path.join(builder.projectDir, 'build/hyperloop/android');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does node handle unix slashes properly on Windows? I always tend to avoid using separators just in case:
var hyperloopBuildPath = path.join(builder.projectDir, 'build', 'hyperloop', 'android');

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, path.join will properly take care of the slashes on Windows


cli.on('build.android.aapt', {
priority: 1100,
/**
* Remove parameters passed to AAPT which are not required anymore since 6.1.0
*
* @param {Object} data Hook data
* @param {Function} callback Callback function
*/
pre: function (data, callback) {
logger.trace('Cleaning AAPT options from changes made by Hyperloop');
var aaptOptions = data.args[1];
var extraPackagesIndex = aaptOptions.indexOf('--extra-packages') + 1;
if (extraPackagesIndex === -1) {
return callback();
}
var extraPackages = aaptOptions[extraPackagesIndex];
var parameterIndex = aaptOptions.indexOf('-S');
var packageNameRegex = /package="(.*)"/;
while (parameterIndex !== -1) {
var resourcePath = aaptOptions[parameterIndex + 1];
if (resourcePath.indexOf(hyperloopBuildPath) !== -1) {
var manifestPathAndFilename = path.join(resourcePath, '../AndroidManifest.xml');
if (fs.existsSync(manifestPathAndFilename)) {
var manifestContent = fs.readFileSync(manifestPathAndFilename).toString();
var packageNameMatch = manifestContent.match(packageNameRegex);
if (packageNameMatch !== null) {
var packageName = packageNameMatch[1];
extraPackages = extraPackages.split(':').filter(n => n !== packageName).join(':');
logger.trace('Removed package ' + packageName + ' from AAPT --extra-packages option');
}
}
aaptOptions.splice(parameterIndex, 2);
logger.trace('Removed AAPT -S resource path ' + resourcePath);
parameterIndex = aaptOptions.indexOf('-S', parameterIndex);
} else {
parameterIndex = aaptOptions.indexOf('-S', parameterIndex + 1);
}
}
aaptOptions[extraPackagesIndex] = extraPackages;
callback();
}
});


cli.on('build.android.dexer', {
priority: 1100,
/**
* Fixes repeated adding of the same JAR to the dexer to avoid crashing
* with a dreaded "already added" exception
*
* @param {Object} data Hook data
* @param {Function} callback Callback function
*/
pre: function (data, callback) {
logger.trace('Cleaning dexer paths from changes made by Hyperloop');
var builder = data.ctx;
var dexerOptions = data.args[1].slice(0, 6);
var dexerPaths = data.args[1].slice(6);
if (builder.androidLibraries.length > 0) {
var fixedDexerPaths = [];
dexerPaths.forEach(function (entryPathAndFilename) {
var isHyperloopExtractedAarPath = entryPathAndFilename.indexOf(hyperloopBuildPath) !== -1;
if (builder.isExternalAndroidLibraryAvailable(entryPathAndFilename) || isHyperloopExtractedAarPath) {
logger.trace('Removed ' + entryPathAndFilename + ' from dexer paths.');
} else {
fixedDexerPaths.push(entryPathAndFilename);
}
}, builder);
data.args[1] = dexerOptions.concat(fixedDexerPaths);
}
callback();
}
});
}