Commit a0f0c42f authored by Jakob Andersen's avatar Jakob Andersen Committed by GitHub

Update gradle example to support x86 in debug mode. (#7606)

* Update gradle example to support x86 in debug mode.

Changed the Flutter Gradle plugin a bit to better fit in with the
Android build.

Fixes #6136
Fixes #6864
Fixes #7539
parent 4cace66d
......@@ -2,8 +2,8 @@ apply plugin: 'com.android.application'
apply plugin: 'flutter'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
compileSdkVersion 25
buildToolsVersion '24.0.2'
lintOptions {
disable 'InvalidPackage'
......@@ -12,6 +12,14 @@ android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
......@@ -19,7 +27,7 @@ flutter {
}
dependencies {
androidTestCompile 'com.android.support:support-annotations:22.0.0'
androidTestCompile 'com.android.support:support-annotations:25.0.0'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
}
implementation-class=org.domokit.sky.gradle.FlutterPlugin
implementation-class=io.flutter.gradle.FlutterPlugin
......@@ -274,6 +274,11 @@ class AndroidDevice extends Device {
if (!_checkForSupportedAdbVersion() || !_checkForSupportedAndroidVersion())
return new LaunchResult.failed();
if (platform != TargetPlatform.android_arm && mode != BuildMode.debug) {
printError('Profile and release builds are only supported on ARM targets.');
return new LaunchResult.failed();
}
printTrace("Stopping app '${package.name}' on $name.");
await stopApp(package);
......
......@@ -18,12 +18,44 @@ import '../globals.dart';
import 'android_sdk.dart';
const String gradleManifestPath = 'android/app/src/main/AndroidManifest.xml';
const String gradleAppOut = 'android/app/build/outputs/apk/app-debug.apk';
const String gradleAppOutV1 = 'android/app/build/outputs/apk/app-debug.apk';
const String gradleAppOutV2 = 'android/app/build/outputs/apk/app.apk';
const String gradleAppOutDir = 'android/app/build/outputs/apk';
enum FlutterPluginVersion {
none,
v1,
v2,
}
bool isProjectUsingGradle() {
return fs.isFileSync('android/build.gradle');
}
FlutterPluginVersion get flutterPluginVersion {
File plugin = fs.file('android/buildSrc/src/main/groovy/FlutterPlugin.groovy');
if (!plugin.existsSync()) {
return FlutterPluginVersion.none;
}
String packageLine = plugin.readAsLinesSync().skip(4).first;
if (packageLine == "package io.flutter.gradle") {
return FlutterPluginVersion.v2;
}
return FlutterPluginVersion.v1;
}
String get gradleAppOut {
switch (flutterPluginVersion) {
case FlutterPluginVersion.none:
// Fall through. Pretend we're v1, and just go with it.
case FlutterPluginVersion.v1:
return gradleAppOutV1;
case FlutterPluginVersion.v2:
return gradleAppOutV2;
}
return null;
}
String locateSystemGradle({ bool ensureExecutable: true }) {
String gradle = _locateSystemGradle();
if (ensureExecutable && gradle != null) {
......@@ -91,29 +123,14 @@ String locateProjectGradlew({ bool ensureExecutable: true }) {
}
}
Future<Null> buildGradleProject(BuildMode buildMode) async {
// Create android/local.properties.
File localProperties = fs.file('android/local.properties');
if (!localProperties.existsSync()) {
localProperties.writeAsStringSync(
'sdk.dir=${androidSdk.directory}\n'
'flutter.sdk=${Cache.flutterRoot}\n'
);
}
// Update the local.settings file with the build mode.
// TODO(devoncarew): It would be nicer if we could pass this information in via a cli flag.
SettingsFile settings = new SettingsFile.parseFromFile(localProperties);
settings.values['flutter.buildMode'] = getModeName(buildMode);
settings.writeContents(localProperties);
Future<String> ensureGradlew() async {
String gradlew = locateProjectGradlew();
if (gradlew == null) {
String gradle = locateSystemGradle();
if (gradle == null) {
throwToolExit(
'Unable to locate gradle. Please configure the path to gradle using \'flutter config --gradle-dir\'.'
'Unable to locate gradle. Please configure the path to gradle using \'flutter config --gradle-dir\'.'
);
} else {
printTrace('Using gradle from $gradle.');
......@@ -130,12 +147,15 @@ Future<Null> buildGradleProject(BuildMode buildMode) async {
}
// Run 'gradle wrapper'.
List<String> command = logger.isVerbose
? <String>[gradle, 'wrapper']
: <String>[gradle, '-q', 'wrapper'];
try {
Status status = logger.startProgress('Running \'gradle wrapper\'...');
int exitcode = await runCommandAndStreamOutput(
<String>[gradle, 'wrapper'],
workingDirectory: 'android',
allowReentrantFlutter: true
command,
workingDirectory: 'android',
allowReentrantFlutter: true
);
status.stop();
if (exitcode != 0)
......@@ -149,10 +169,44 @@ Future<Null> buildGradleProject(BuildMode buildMode) async {
throwToolExit('Unable to build android/gradlew.');
}
return gradlew;
}
Future<Null> buildGradleProject(BuildMode buildMode) async {
// Create android/local.properties.
File localProperties = fs.file('android/local.properties');
if (!localProperties.existsSync()) {
localProperties.writeAsStringSync(
'sdk.dir=${androidSdk.directory}\n'
'flutter.sdk=${Cache.flutterRoot}\n'
);
}
// Update the local.properties file with the build mode.
// FlutterPlugin v1 reads local.properties to determine build mode. Plugin v2
// uses the standard Android way to determine what to build, but we still
// update local.properties, in case we want to use it in the future.
String buildModeName = getModeName(buildMode);
SettingsFile settings = new SettingsFile.parseFromFile(localProperties);
settings.values['flutter.buildMode'] = buildModeName;
settings.writeContents(localProperties);
String gradlew = await ensureGradlew();
switch (flutterPluginVersion) {
case FlutterPluginVersion.none:
// Fall through. Pretend it's v1, and just go for it.
case FlutterPluginVersion.v1:
return buildGradleProjectV1(gradlew);
case FlutterPluginVersion.v2:
return buildGradleProjectV2(gradlew, buildModeName);
}
}
Future<Null> buildGradleProjectV1(String gradlew) async {
// Run 'gradlew build'.
Status status = logger.startProgress('Running \'gradlew build\'...');
int exitcode = await runCommandAndStreamOutput(
<String>[fs.file('android/gradlew').absolute.path, 'build'],
<String>[fs.file(gradlew).absolute.path, 'build'],
workingDirectory: 'android',
allowReentrantFlutter: true
);
......@@ -161,8 +215,34 @@ Future<Null> buildGradleProject(BuildMode buildMode) async {
if (exitcode != 0)
throwToolExit('Gradlew failed: $exitcode', exitCode: exitcode);
File apkFile = fs.file(gradleAppOut);
printStatus('Built $gradleAppOut (${getSizeAsMB(apkFile.lengthSync())}).');
File apkFile = fs.file(gradleAppOutV1);
printStatus('Built $gradleAppOutV1 (${getSizeAsMB(apkFile.lengthSync())}).');
}
Future<Null> buildGradleProjectV2(String gradlew, String buildModeName) async {
String assembleTask = "assemble${toTitleCase(buildModeName)}";
// Run 'gradlew assemble<BuildMode>'.
Status status = logger.startProgress('Running \'gradlew $assembleTask\'...');
String gradlewPath = fs.file(gradlew).absolute.path;
List<String> command = logger.isVerbose
? <String>[gradlewPath, assembleTask]
: <String>[gradlewPath, '-q', assembleTask];
int exitcode = await runCommandAndStreamOutput(
command,
workingDirectory: 'android',
allowReentrantFlutter: true
);
status.stop();
if (exitcode != 0)
throwToolExit('Gradlew failed: $exitcode', exitCode: exitcode);
String apkFilename = 'app-$buildModeName.apk';
File apkFile = fs.file('$gradleAppOutDir/$apkFilename');
// Copy the APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
apkFile.copySync('$gradleAppOutDir/app.apk');
printStatus('Built $apkFilename (${getSizeAsMB(apkFile.lengthSync())}).');
}
class _GradleFile {
......
......@@ -227,21 +227,20 @@ class BuildApkCommand extends BuildSubCommand {
await super.runCommand();
TargetPlatform targetPlatform = _getTargetPlatform(argResults['target-arch']);
if (targetPlatform != TargetPlatform.android_arm && getBuildMode() != BuildMode.debug)
BuildMode buildMode = getBuildMode();
if (targetPlatform != TargetPlatform.android_arm && buildMode != BuildMode.debug)
throwToolExit('Profile and release builds are only supported on ARM targets.');
if (isProjectUsingGradle()) {
if (targetPlatform != TargetPlatform.android_arm)
throwToolExit('Gradle builds only support ARM targets.');
await buildAndroidWithGradle(
TargetPlatform.android_arm,
getBuildMode(),
targetPlatform,
buildMode,
target: targetFile
);
} else {
await buildAndroid(
targetPlatform,
getBuildMode(),
buildMode,
force: true,
manifest: argResults['manifest'],
resources: argResults['resources'],
......@@ -595,6 +594,9 @@ Future<Null> buildAndroidWithGradle(
bool force: false,
String target
}) async {
if (platform != TargetPlatform.android_arm && buildMode != BuildMode.debug) {
throwToolExit('Profile and release builds are only supported on ARM targets.');
}
// Validate that we can find an android sdk.
if (androidSdk == null)
throwToolExit('No Android SDK found. Try setting the ANDROID_HOME environment variable.');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment