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

feat!: unify & fix gradle library/tooling overrides #1212

Merged
merged 32 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
df22365
enhancement: Control SDK versions and other default projects in one p…
breautek Apr 10, 2021
e7edcf8
enhancement: Control SDK versions and other default projects in one p…
breautek Apr 10, 2021
570a7d1
fix: target/compile sdk usage
breautek Apr 10, 2021
a6d3519
refactor: cleanup gradle process (#1)
erisu Apr 21, 2021
44a7697
chore: cleanup and remove unused changes
erisu Apr 21, 2021
0a46132
chore: remove more unneeded FILE_PATH
erisu Apr 21, 2021
cb857c5
chore: fix lint error
erisu Apr 21, 2021
944975d
revert change intended to be part of a different PR
breautek Apr 19, 2021
f68b488
chore: apply changes to revert to fit new changes
erisu Apr 21, 2021
09b6247
fix: Ensure proper types
breautek Apr 24, 2021
8b09f07
breaking: Removed TempateFile class
breautek Apr 25, 2021
560d992
refactor: Use the sync version of properties editor
breautek May 9, 2021
9ef324d
Gh 1178 fix sdk use gradlearg fix (#2)
erisu May 11, 2021
9509670
refactor: remove unused mock variables
raphinesse Jun 24, 2021
6fa10a1
Update bin/templates/cordova/lib/builders/ProjectBuilder.js
breautek Jun 24, 2021
ea64965
Update bin/lib/create.js
breautek Jun 24, 2021
132c4ef
fix: const naming (review suggestion)
erisu Jul 4, 2021
203fa79
fix: use defaults for framework building
erisu Jul 5, 2021
dce90e9
chore: apply review suggestion
erisu Jul 5, 2021
c56aef6
chore: rename config.json & defaults.json (review suggestions)
erisu Jul 5, 2021
4b7ac21
refactor: updateUserProjectGradleConfig method
erisu Jul 5, 2021
24c9452
refactor: minor changes in updateUserProjectGradleConfig
raphinesse Jul 5, 2021
cf9825c
refactor: major changes in updateUserProjectGradleConfig
raphinesse Jul 5, 2021
a16d183
fix: wrong handling of missing preferences
raphinesse Jul 5, 2021
3818d85
fix: usage of undefined this
raphinesse Jul 5, 2021
10e8718
fix(create.spec): mocking of getPreference
raphinesse Jul 5, 2021
afd8f48
test(check_reqs): reduce diff size
raphinesse Jul 5, 2021
ed06d9d
refactor: add wrapper to load gradle config defaults
raphinesse Jul 5, 2021
c40cdaf
fix(check_reqs): get_target
raphinesse Jul 5, 2021
54dac43
fix(check_reqs.spec): return correct types from mocks
raphinesse Jul 5, 2021
8e3f868
revert to using get_target in create
raphinesse Jul 5, 2021
171c420
fix: e2e test
raphinesse Jul 5, 2021
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ example
/test/androidx/gradle
/test/androidx/gradlew
/test/androidx/gradlew.bat
/test/androidx/cdv-gradle-config.json

/test/assets/www/.tmp*
/test/assets/www/cordova.js
Expand Down
14 changes: 7 additions & 7 deletions bin/lib/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var fs = require('fs-extra');
var utils = require('../templates/cordova/lib/utils');
var check_reqs = require('./../templates/cordova/lib/check_reqs');
var ROOT = path.join(__dirname, '..', '..');
const { createEditor } = require('properties-parser');

var CordovaError = require('cordova-common').CordovaError;
var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
Expand All @@ -42,16 +43,12 @@ function getFrameworkDir (projectPath, shared) {
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
}

function copyJsAndLibrary (projectPath, shared, projectName, isLegacy) {
function copyJsAndLibrary (projectPath, shared, projectName, targetAPI) {
var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
var app_path = path.join(projectPath, 'app', 'src', 'main');
const platform_www = path.join(projectPath, 'platform_www');

if (isLegacy) {
app_path = projectPath;
}

fs.copySync(srcCordovaJsPath, path.join(app_path, 'assets', 'www', 'cordova.js'));

// Copy the cordova.js file to platforms/<platform>/platform_www/
Expand All @@ -69,11 +66,14 @@ function copyJsAndLibrary (projectPath, shared, projectName, isLegacy) {
} else {
fs.ensureDirSync(nestedCordovaLibPath);
fs.copySync(path.join(ROOT, 'framework', 'AndroidManifest.xml'), path.join(nestedCordovaLibPath, 'AndroidManifest.xml'));
fs.copySync(path.join(ROOT, 'framework', 'project.properties'), path.join(nestedCordovaLibPath, 'project.properties'));
const propertiesEditor = createEditor(path.join(ROOT, 'framework', 'project.properties'));
propertiesEditor.set('target', targetAPI);
propertiesEditor.save(path.join(nestedCordovaLibPath, 'project.properties'));
fs.copySync(path.join(ROOT, 'framework', 'build.gradle'), path.join(nestedCordovaLibPath, 'build.gradle'));
fs.copySync(path.join(ROOT, 'framework', 'cordova.gradle'), path.join(nestedCordovaLibPath, 'cordova.gradle'));
fs.copySync(path.join(ROOT, 'framework', 'repositories.gradle'), path.join(nestedCordovaLibPath, 'repositories.gradle'));
fs.copySync(path.join(ROOT, 'framework', 'src'), path.join(nestedCordovaLibPath, 'src'));
fs.copySync(path.join(ROOT, 'framework', 'cdv-gradle-config-defaults.json'), path.join(projectPath, 'cdv-gradle-config.json'));
}
}

Expand Down Expand Up @@ -277,7 +277,7 @@ exports.create = function (project_path, config, options, events) {
fs.ensureDirSync(path.join(app_path, 'libs'));

// copy cordova.js, cordova.jar
exports.copyJsAndLibrary(project_path, options.link, safe_activity_name);
exports.copyJsAndLibrary(project_path, options.link, safe_activity_name, target_api);

// Set up ther Android Studio paths
var java_path = path.join(app_path, 'java');
Expand Down
11 changes: 10 additions & 1 deletion bin/templates/cordova/lib/builders/ProjectBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,11 @@ class ProjectBuilder {
}).then(function () {
return self.prepBuildFiles();
}).then(() => {
const config = this._getCordovaConfig();
// update/set the distributionUrl in the gradle-wrapper.properties
const gradleWrapperPropertiesPath = path.join(self.root, 'gradle/wrapper/gradle-wrapper.properties');
const gradleWrapperProperties = createEditor(gradleWrapperPropertiesPath);
const distributionUrl = process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL || 'https://services.gradle.org/distributions/gradle-6.8.3-all.zip';
const distributionUrl = process.env.CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL || `https://services.gradle.org/distributions/gradle-${config.GRADLE_VERSION}-all.zip`;
gradleWrapperProperties.set('distributionUrl', distributionUrl);
gradleWrapperProperties.save();

Expand All @@ -287,6 +288,14 @@ class ProjectBuilder {
});
}

/**
* @private
* @returns The user defined configs
*/
_getCordovaConfig () {
return fs.readJSONSync(path.join(this.root, 'cdv-gradle-config.json'));
}

/*
* Builds the project with gradle.
* Returns a promise.
Expand Down
43 changes: 13 additions & 30 deletions bin/templates/cordova/lib/check_reqs.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ var fs = require('fs-extra');
const { forgivingWhichSync, isWindows, isDarwin } = require('./utils');
const java = require('./env/java');
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
var PROJECT_ROOT = path.join(__dirname, '..', '..');
const { CordovaError, ConfigParser, events } = require('cordova-common');
var android_sdk = require('./android_sdk');
const { createEditor } = require('properties-parser');
const semver = require('semver');
const { SDK_VERSION } = require('./gradle-config-defaults');

const EXPECTED_JAVA_VERSION = '1.8.x';

Expand All @@ -36,44 +35,28 @@ const EXPECTED_JAVA_VERSION = '1.8.x';
Object.assign(module.exports, { isWindows, isDarwin });

/**
* @description Get valid target from framework/project.properties if run from this repo
* Otherwise get target from project.properties file within a generated cordova-android project
* @returns {string} The android target in format "android-${target}"
*/
module.exports.get_target = function () {
const projectPropertiesPaths = [
path.join(REPO_ROOT, 'framework', 'project.properties'),
path.join(PROJECT_ROOT, 'project.properties')
];

// Get the minimum required target API from the framework.
let target = projectPropertiesPaths.filter(filePath => fs.existsSync(filePath))
.map(filePath => createEditor(filePath).get('target'))
.pop();
const userTargetSdkVersion = getUserTargetSdkVersion();

if (!target) {
throw new Error(`We could not locate the target from the "project.properties" at either "${projectPropertiesPaths.join('", "')}".`);
if (userTargetSdkVersion && userTargetSdkVersion < SDK_VERSION) {
events.emit('warn', `android-targetSdkVersion should be greater than or equal to ${SDK_VERSION}.`);
}

return `android-${Math.max(userTargetSdkVersion, SDK_VERSION)}`;
};

/** @returns {number} target sdk or 0 if undefined */
function getUserTargetSdkVersion () {
// If the repo config.xml file exists, find the desired targetSdkVersion.
const configFile = path.join(REPO_ROOT, 'config.xml');
if (!fs.existsSync(configFile)) return target;
if (!fs.existsSync(configFile)) return 0;

const configParser = new ConfigParser(configFile);
const desiredAPI = parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);

if (!isNaN(desiredAPI)) {
const minimumAPI = parseInt(target.split('-').pop(), 10);

if (desiredAPI >= minimumAPI) {
target = `android-${desiredAPI}`;
} else {
events.emit('warn', `android-targetSdkVersion should be greater than or equal to ${minimumAPI}.`);
}
}

return target;
};
const targetSdkVersion = parseInt(configParser.getPreference('android-targetSdkVersion', 'android'), 10);
return isNaN(targetSdkVersion) ? 0 : targetSdkVersion;
}

module.exports.get_gradle_wrapper = function () {
var androidStudioPath;
Expand Down
30 changes: 30 additions & 0 deletions bin/templates/cordova/lib/gradle-config-defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*!
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/

const ABS_MODULE_PATH = '/framework/cdv-gradle-config-defaults.json';

try {
// Try relative require first, …
const REPO_ROOT = '../../../..';
module.exports = require(REPO_ROOT + ABS_MODULE_PATH);
} catch (error) {
// … then fall back to installed-package require
if (error.code !== 'MODULE_NOT_FOUND') throw error;
module.exports = require('cordova-android' + ABS_MODULE_PATH);
}
4 changes: 2 additions & 2 deletions bin/templates/cordova/lib/plugin-build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ dependencies {
}

android {
compileSdkVersion cdvCompileSdkVersion
buildToolsVersion cdvBuildToolsVersion
compileSdkVersion cordovaConfig.SDK_VERSION
buildToolsVersion cordovaConfig.BUILD_TOOLS_VERSION

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6
Expand Down
97 changes: 75 additions & 22 deletions bin/templates/cordova/lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var PlatformJson = require('cordova-common').PlatformJson;
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
const utils = require('./utils');
const gradleConfigDefaults = require('./gradle-config-defaults');

const GradlePropertiesParser = require('./config/GradlePropertiesParser');

Expand All @@ -55,29 +56,11 @@ module.exports.prepare = function (cordovaProject, options) {

this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);

// Get the min SDK version from config.xml
const minSdkVersion = this._config.getPreference('android-minSdkVersion', 'android');
const maxSdkVersion = this._config.getPreference('android-maxSdkVersion', 'android');
const targetSdkVersion = this._config.getPreference('android-targetSdkVersion', 'android');
const isGradlePluginKotlinEnabled = this._config.getPreference('GradlePluginKotlinEnabled', 'android');
const gradlePluginKotlinCodeStyle = this._config.getPreference('GradlePluginKotlinCodeStyle', 'android');
const androidXAppCompatVersion = this._config.getPreference('AndroidXAppCompatVersion', 'android');

const gradlePropertiesUserConfig = {};
if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = minSdkVersion;
if (maxSdkVersion) gradlePropertiesUserConfig.cdvMaxSdkVersion = maxSdkVersion;
if (targetSdkVersion) gradlePropertiesUserConfig.cdvTargetSdkVersion = targetSdkVersion;
if (args.jvmargs) gradlePropertiesUserConfig['org.gradle.jvmargs'] = args.jvmargs;
if (isGradlePluginKotlinEnabled) {
gradlePropertiesUserConfig['kotlin.code.style'] = gradlePluginKotlinCodeStyle || 'official';
}

if (androidXAppCompatVersion) {
gradlePropertiesUserConfig.cdvAndroidXAppCompatVersion = androidXAppCompatVersion;
}
// Update Gradle cdv-gradle-config.json
updateUserProjectGradleConfig(this);

const gradlePropertiesParser = new GradlePropertiesParser(this.locations.root);
gradlePropertiesParser.configure(gradlePropertiesUserConfig);
// Update Project's Gradle Properties
updateUserProjectGradlePropertiesConfig(this, args);

// Update own www dir with project's www assets and plugins' assets and js-files
return Promise.resolve(updateWww(cordovaProject, this.locations)).then(function () {
Expand All @@ -92,6 +75,76 @@ module.exports.prepare = function (cordovaProject, options) {
});
};

/** @param {PlatformApi} project */
function updateUserProjectGradleConfig (project) {
// Generate project gradle config
const projectGradleConfig = {
...gradleConfigDefaults,
...getUserGradleConfig(project._config)
};

// Write out changes
const projectGradleConfigPath = path.join(project.root, 'cdv-gradle-config.json');
fs.writeJSONSync(projectGradleConfigPath, projectGradleConfig, { spaces: 2 });
}

function getUserGradleConfig (configXml) {
const configXmlToGradleMapping = [
{ xmlKey: 'android-minSdkVersion', gradleKey: 'MIN_SDK_VERSION', type: Number },
{ xmlKey: 'android-maxSdkVersion', gradleKey: 'MAX_SDK_VERSION', type: Number },
{ xmlKey: 'android-targetSdkVersion', gradleKey: 'SDK_VERSION', type: Number },
{ xmlKey: 'android-buildToolsVersion', gradleKey: 'BUILD_TOOLS_VERSION', type: String },
{ xmlKey: 'GradleVersion', gradleKey: 'GRADLE_VERSION', type: String },
{ xmlKey: 'AndroidGradlePluginVersion', gradleKey: 'AGP_VERSION', type: String },
{ xmlKey: 'GradlePluginKotlinVersion', gradleKey: 'KOTLIN_VERSION', type: String },
{ xmlKey: 'AndroidXAppCompatVersion', gradleKey: 'ANDROIDX_APP_COMPAT_VERSION', type: String },
{ xmlKey: 'GradlePluginGoogleServicesVersion', gradleKey: 'GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION', type: String },
{ xmlKey: 'GradlePluginGoogleServicesEnabled', gradleKey: 'IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED', type: Boolean },
{ xmlKey: 'GradlePluginKotlinEnabled', gradleKey: 'IS_GRADLE_PLUGIN_KOTLIN_ENABLED', type: Boolean }
];

return configXmlToGradleMapping.reduce((config, mapping) => {
const rawValue = configXml.getPreference(mapping.xmlKey, 'android');

// ignore missing preferences (which occur as '')
if (rawValue) {
config[mapping.gradleKey] = parseStringAsType(rawValue, mapping.type);
}

return config;
}, {});
}

/** Converts given string to given type */
function parseStringAsType (value, type) {
switch (type) {
case String:
return String(value);
case Number:
return parseFloat(value);
case Boolean:
return value.toLowerCase() === 'true';
default:
throw new CordovaError('Invalid type: ' + type);
}
}

function updateUserProjectGradlePropertiesConfig (project, args) {
const gradlePropertiesUserConfig = {};

// Get the min SDK version from config.xml
if (args.jvmargs) gradlePropertiesUserConfig['org.gradle.jvmargs'] = args.jvmargs;

const isGradlePluginKotlinEnabled = project._config.getPreference('GradlePluginKotlinEnabled', 'android');
if (isGradlePluginKotlinEnabled) {
const gradlePluginKotlinCodeStyle = project._config.getPreference('GradlePluginKotlinCodeStyle', 'android');
gradlePropertiesUserConfig['kotlin.code.style'] = gradlePluginKotlinCodeStyle || 'official';
}

const gradlePropertiesParser = new GradlePropertiesParser(project.root);
gradlePropertiesParser.configure(gradlePropertiesUserConfig);
}

module.exports.clean = function (options) {
// A cordovaProject isn't passed into the clean() function, because it might have
// been called from the platform shell script rather than the CLI. Check for the
Expand Down