mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
194 lines
5.9 KiB
Dart
194 lines
5.9 KiB
Dart
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:path/path.dart' as path;
|
|
|
|
import '../base/logger.dart';
|
|
import '../base/os.dart';
|
|
import '../base/process.dart';
|
|
import '../base/utils.dart';
|
|
import '../build_info.dart';
|
|
import '../cache.dart';
|
|
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';
|
|
|
|
bool isProjectUsingGradle() {
|
|
return FileSystemEntity.isFileSync('android/build.gradle');
|
|
}
|
|
|
|
String locateSystemGradle({ bool ensureExecutable: true }) {
|
|
String gradle = _locateSystemGradle();
|
|
if (ensureExecutable && gradle != null) {
|
|
File file = new File(gradle);
|
|
if (file.existsSync())
|
|
os.makeExecutable(file);
|
|
}
|
|
return gradle;
|
|
}
|
|
|
|
String _locateSystemGradle() {
|
|
// See if the user has explicitly configured gradle-dir.
|
|
String gradleDir = config.getValue('gradle-dir');
|
|
if (gradleDir != null) {
|
|
if (FileSystemEntity.isFileSync(gradleDir))
|
|
return gradleDir;
|
|
return path.join(gradleDir, 'bin', 'gradle');
|
|
}
|
|
|
|
// Look relative to Android Studio.
|
|
String studioPath = config.getValue('android-studio-dir');
|
|
|
|
if (studioPath == null && os.isMacOS) {
|
|
final String kDefaultMacPath = '/Applications/Android Studio.app';
|
|
if (FileSystemEntity.isDirectorySync(kDefaultMacPath))
|
|
studioPath = kDefaultMacPath;
|
|
}
|
|
|
|
if (studioPath != null) {
|
|
// '/Applications/Android Studio.app/Contents/gradle/gradle-2.10/bin/gradle'
|
|
if (os.isMacOS && !studioPath.endsWith('Contents'))
|
|
studioPath = path.join(studioPath, 'Contents');
|
|
|
|
Directory dir = new Directory(path.join(studioPath, 'gradle'));
|
|
if (dir.existsSync()) {
|
|
// We find the first valid gradle directory.
|
|
for (FileSystemEntity entity in dir.listSync()) {
|
|
if (entity is Directory && path.basename(entity.path).startsWith('gradle-')) {
|
|
String executable = path.join(entity.path, 'bin', 'gradle');
|
|
if (FileSystemEntity.isFileSync(executable))
|
|
return executable;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Use 'which'.
|
|
File file = os.which('gradle');
|
|
if (file != null)
|
|
return file.path;
|
|
|
|
// We couldn't locate gradle.
|
|
return null;
|
|
}
|
|
|
|
String locateProjectGradlew({ bool ensureExecutable: true }) {
|
|
final String path = 'android/gradlew';
|
|
|
|
if (FileSystemEntity.isFileSync(path)) {
|
|
if (ensureExecutable)
|
|
os.makeExecutable(new File(path));
|
|
return path;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
Future<int> buildGradleProject(BuildMode buildMode) async {
|
|
// Create android/local.properties.
|
|
File localProperties = new 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);
|
|
|
|
String gradlew = locateProjectGradlew();
|
|
|
|
if (gradlew == null) {
|
|
String gradle = locateSystemGradle();
|
|
if (gradle == null) {
|
|
printError(
|
|
'Unable to locate gradle. Please configure the path to gradle using \'flutter config --gradle\'.'
|
|
);
|
|
return 1;
|
|
} else {
|
|
printTrace('Using gradle from $gradle.');
|
|
}
|
|
|
|
// Stamp the android/app/build.gradle file with the current android sdk and build tools version.
|
|
File appGradleFile = new File('android/app/build.gradle');
|
|
if (appGradleFile.existsSync()) {
|
|
_GradleFile gradleFile = new _GradleFile.parse(appGradleFile);
|
|
AndroidSdkVersion sdkVersion = androidSdk.latestVersion;
|
|
gradleFile.replace('compileSdkVersion', "${sdkVersion.sdkLevel}");
|
|
gradleFile.replace('buildToolsVersion', "'${sdkVersion.buildToolsVersionName}'");
|
|
gradleFile.writeContents(appGradleFile);
|
|
}
|
|
|
|
// Run 'gradle wrapper'.
|
|
try {
|
|
Status status = logger.startProgress('Running \'gradle wrapper\'...');
|
|
int exitcode = await runCommandAndStreamOutput(
|
|
<String>[gradle, 'wrapper'],
|
|
workingDirectory: 'android',
|
|
allowReentrantFlutter: true
|
|
);
|
|
status.stop(showElapsedTime: true);
|
|
if (exitcode != 0)
|
|
return exitcode;
|
|
} catch (error) {
|
|
printError('$error');
|
|
return 1;
|
|
}
|
|
|
|
gradlew = locateProjectGradlew();
|
|
if (gradlew == null) {
|
|
printError('Unable to build android/gradlew.');
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// Run 'gradlew build'.
|
|
Status status = logger.startProgress('Running \'gradlew build\'...');
|
|
int exitcode = await runCommandAndStreamOutput(
|
|
<String>[new File('android/gradlew').absolute.path, 'build'],
|
|
workingDirectory: 'android',
|
|
allowReentrantFlutter: true
|
|
);
|
|
status.stop(showElapsedTime: true);
|
|
|
|
if (exitcode == 0) {
|
|
File apkFile = new File(gradleAppOut);
|
|
printStatus('Built $gradleAppOut (${getSizeAsMB(apkFile.lengthSync())}).');
|
|
}
|
|
|
|
return exitcode;
|
|
}
|
|
|
|
class _GradleFile {
|
|
_GradleFile.parse(File file) {
|
|
contents = file.readAsStringSync();
|
|
}
|
|
|
|
String contents;
|
|
|
|
void replace(String key, String newValue) {
|
|
// Replace 'ws key ws value' with the new value.
|
|
final RegExp regex = new RegExp('\\s+$key\\s+(\\S+)', multiLine: true);
|
|
Match match = regex.firstMatch(contents);
|
|
if (match != null) {
|
|
String oldValue = match.group(1);
|
|
int offset = match.end - oldValue.length;
|
|
contents = contents.substring(0, offset) + newValue + contents.substring(match.end);
|
|
}
|
|
}
|
|
|
|
void writeContents(File file) {
|
|
file.writeAsStringSync(contents);
|
|
}
|
|
}
|