mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Test Gradle on Windows (#42709)
This commit is contained in:
parent
898e6fe3c6
commit
30493a35b6
@ -722,11 +722,6 @@ Map<String, String> _initGradleEnvironment() {
|
|||||||
final Map<String, String> gradleEnvironment = _initGradleEnvironment();
|
final Map<String, String> gradleEnvironment = _initGradleEnvironment();
|
||||||
|
|
||||||
Future<void> _runHostOnlyDeviceLabTests() async {
|
Future<void> _runHostOnlyDeviceLabTests() async {
|
||||||
if (Platform.isWindows) {
|
|
||||||
// TODO(ianh): remove when https://github.com/flutter/flutter/issues/36311 fixed by https://github.com/flutter/flutter/pull/42709
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Please don't add more tests here. We should not be using the devicelab
|
// Please don't add more tests here. We should not be using the devicelab
|
||||||
// logic to run tests outside devicelab, that's just confusing.
|
// logic to run tests outside devicelab, that's just confusing.
|
||||||
// Instead, create tests that are not devicelab tests, and run those.
|
// Instead, create tests that are not devicelab tests, and run those.
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that AARs can be built on module projects.
|
/// Tests that AARs can be built on module projects.
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
@ -182,10 +182,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
// JIT snapshots.
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], debugAar);
|
], debugAar);
|
||||||
|
|
||||||
return TaskResult.success(null);
|
return TaskResult.success(null);
|
||||||
|
@ -10,7 +10,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that AARs can be built on plugin projects.
|
/// Tests that AARs can be built on plugin projects.
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that Jetifier can translate plugins that use support libraries.
|
/// Tests that Jetifier can translate plugins that use support libraries.
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
@ -56,6 +56,12 @@ Future<void> main() async {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
section('Update proguard rules');
|
||||||
|
|
||||||
|
// Don't obfuscate the input class files, since the test is checking if some classes are in the DEX.
|
||||||
|
final File proguardRules = File(path.join(projectDir.path, 'android', 'app', 'proguard-rules.pro'));
|
||||||
|
proguardRules.writeAsStringSync('-dontobfuscate', flush: true);
|
||||||
|
|
||||||
section('Build release APK');
|
section('Build release APK');
|
||||||
|
|
||||||
await inDirectory(projectDir, () async {
|
await inDirectory(projectDir, () async {
|
||||||
|
@ -10,7 +10,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that [settings_aar.gradle] is created when possible.
|
/// Tests that [settings_aar.gradle] is created when possible.
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter_devicelab/framework/apk_utils.dart';
|
import 'package:flutter_devicelab/framework/apk_utils.dart';
|
||||||
import 'package:flutter_devicelab/framework/framework.dart';
|
import 'package:flutter_devicelab/framework/framework.dart';
|
||||||
@ -10,6 +11,11 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
final Iterable<String> baseAabFiles = <String>[
|
||||||
|
'base/dex/classes.dex',
|
||||||
|
'base/manifest/AndroidManifest.xml',
|
||||||
|
];
|
||||||
|
final Iterable<String> flutterAabAssets = flutterAssets.map((String file) => 'base/$file');
|
||||||
await task(() async {
|
await task(() async {
|
||||||
try {
|
try {
|
||||||
await runProjectTest((FlutterProject project) async {
|
await runProjectTest((FlutterProject project) async {
|
||||||
@ -26,8 +32,8 @@ Future<void> main() async {
|
|||||||
'app-release.aab',
|
'app-release.aab',
|
||||||
);
|
);
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'base/manifest/AndroidManifest.xml',
|
...baseAabFiles,
|
||||||
'base/dex/classes.dex',
|
...flutterAabAssets,
|
||||||
'base/lib/arm64-v8a/libapp.so',
|
'base/lib/arm64-v8a/libapp.so',
|
||||||
'base/lib/arm64-v8a/libflutter.so',
|
'base/lib/arm64-v8a/libflutter.so',
|
||||||
'base/lib/armeabi-v7a/libapp.so',
|
'base/lib/armeabi-v7a/libapp.so',
|
||||||
@ -36,6 +42,10 @@ Future<void> main() async {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await runProjectTest((FlutterProject project) async {
|
await runProjectTest((FlutterProject project) async {
|
||||||
|
if (Platform.isWindows) {
|
||||||
|
// https://github.com/flutter/flutter/issues/42985
|
||||||
|
return;
|
||||||
|
}
|
||||||
section('App bundle content using flavors without explicit target platform');
|
section('App bundle content using flavors without explicit target platform');
|
||||||
// Add a few flavors.
|
// Add a few flavors.
|
||||||
await project.addProductFlavors(<String> [
|
await project.addProductFlavors(<String> [
|
||||||
@ -57,8 +67,8 @@ Future<void> main() async {
|
|||||||
'app-production-release.aab',
|
'app-production-release.aab',
|
||||||
);
|
);
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'base/manifest/AndroidManifest.xml',
|
...baseAabFiles,
|
||||||
'base/dex/classes.dex',
|
...flutterAabAssets,
|
||||||
'base/lib/arm64-v8a/libapp.so',
|
'base/lib/arm64-v8a/libapp.so',
|
||||||
'base/lib/arm64-v8a/libflutter.so',
|
'base/lib/arm64-v8a/libflutter.so',
|
||||||
'base/lib/armeabi-v7a/libapp.so',
|
'base/lib/armeabi-v7a/libapp.so',
|
||||||
@ -93,8 +103,8 @@ Future<void> main() async {
|
|||||||
'app-flavor_underscore-release.aab',
|
'app-flavor_underscore-release.aab',
|
||||||
);
|
);
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'base/manifest/AndroidManifest.xml',
|
...baseAabFiles,
|
||||||
'base/dex/classes.dex',
|
...flutterAabAssets,
|
||||||
'base/lib/arm64-v8a/libapp.so',
|
'base/lib/arm64-v8a/libapp.so',
|
||||||
'base/lib/arm64-v8a/libflutter.so',
|
'base/lib/arm64-v8a/libflutter.so',
|
||||||
'base/lib/armeabi-v7a/libapp.so',
|
'base/lib/armeabi-v7a/libapp.so',
|
||||||
@ -128,8 +138,8 @@ Future<void> main() async {
|
|||||||
'app-production-release.aab',
|
'app-production-release.aab',
|
||||||
);
|
);
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'base/manifest/AndroidManifest.xml',
|
...baseAabFiles,
|
||||||
'base/dex/classes.dex',
|
...flutterAabAssets,
|
||||||
'base/lib/arm64-v8a/libapp.so',
|
'base/lib/arm64-v8a/libapp.so',
|
||||||
'base/lib/arm64-v8a/libflutter.so',
|
'base/lib/arm64-v8a/libflutter.so',
|
||||||
'base/lib/armeabi-v7a/libapp.so',
|
'base/lib/armeabi-v7a/libapp.so',
|
||||||
@ -153,10 +163,9 @@ Future<void> main() async {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final Iterable<String> bundleFiles = await getFilesInAppBundle(releaseBundle);
|
final Iterable<String> bundleFiles = await getFilesInAppBundle(releaseBundle);
|
||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
'base/manifest/AndroidManifest.xml',
|
...baseAabFiles,
|
||||||
'base/dex/classes.dex',
|
...flutterAabAssets,
|
||||||
'base/lib/armeabi-v7a/libapp.so',
|
'base/lib/armeabi-v7a/libapp.so',
|
||||||
'base/lib/armeabi-v7a/libflutter.so',
|
'base/lib/armeabi-v7a/libflutter.so',
|
||||||
], bundleFiles);
|
], bundleFiles);
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that projects can include plugins that have a transtive dependency in common.
|
/// Tests that projects can include plugins that have a transtive dependency in common.
|
||||||
/// For more info see: https://github.com/flutter/flutter/issues/27254.
|
/// For more info see: https://github.com/flutter/flutter/issues/27254.
|
||||||
|
@ -21,12 +21,10 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...baseApkFiles,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
'lib/arm64-v8a/libflutter.so',
|
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
|
'lib/arm64-v8a/libflutter.so',
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
'lib/x86_64/libflutter.so',
|
'lib/x86_64/libflutter.so',
|
||||||
@ -48,18 +46,14 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/arm64-v8a/libflutter.so',
|
|
||||||
'lib/arm64-v8a/libapp.so',
|
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
|
'lib/arm64-v8a/libflutter.so',
|
||||||
|
'lib/arm64-v8a/libapp.so',
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(debugAssets, apkFiles);
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], apkFiles);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await runPluginProjectTest((FlutterPluginProject pluginProject) async {
|
await runPluginProjectTest((FlutterPluginProject pluginProject) async {
|
||||||
@ -71,18 +65,14 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/arm64-v8a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(debugAssets, apkFiles);
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], apkFiles);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await runPluginProjectTest((FlutterPluginProject pluginProject) async {
|
await runPluginProjectTest((FlutterPluginProject pluginProject) async {
|
||||||
@ -95,31 +85,23 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
], armApkFiles);
|
], armApkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(debugAssets, armApkFiles);
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], armApkFiles);
|
|
||||||
|
|
||||||
final Iterable<String> arm64ApkFiles = await getFilesInApk(pluginProject.releaseArm64ApkPath);
|
final Iterable<String> arm64ApkFiles = await getFilesInApk(pluginProject.releaseArm64ApkPath);
|
||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/arm64-v8a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
], arm64ApkFiles);
|
], arm64ApkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(debugAssets, arm64ApkFiles);
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], arm64ApkFiles);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await runProjectTest((FlutterProject project) async {
|
await runProjectTest((FlutterProject project) async {
|
||||||
|
@ -21,10 +21,8 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...baseApkFiles,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
@ -32,6 +30,7 @@ Future<void> main() async {
|
|||||||
], apkFiles);
|
], apkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(<String>[
|
||||||
|
'lib/arm64-v8a/libapp.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
'lib/x86/libapp.so',
|
'lib/x86/libapp.so',
|
||||||
'lib/x86_64/libapp.so',
|
'lib/x86_64/libapp.so',
|
||||||
@ -48,10 +47,8 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...baseApkFiles,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
'lib/x86_64/libflutter.so',
|
'lib/x86_64/libflutter.so',
|
||||||
@ -74,10 +71,8 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...baseApkFiles,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
// Debug mode intentionally includes `x86` and `x86_64`.
|
// Debug mode intentionally includes `x86` and `x86_64`.
|
||||||
'lib/x86/libflutter.so',
|
'lib/x86/libflutter.so',
|
||||||
'lib/x86_64/libflutter.so',
|
'lib/x86_64/libflutter.so',
|
||||||
@ -99,17 +94,15 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(<String>[
|
||||||
|
...debugAssets,
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/arm64-v8a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -122,17 +115,15 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'classes.dex',
|
...baseApkFiles,
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/arm64-v8a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
|
|
||||||
checkItDoesNotContain<String>(<String>[
|
checkItDoesNotContain<String>(<String>[
|
||||||
|
...debugAssets,
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], apkFiles);
|
], apkFiles);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
/// Tests that plugins that don't define a `androidx.annotation:annotation:+` or
|
/// Tests that plugins that don't define a `androidx.annotation:annotation:+` or
|
||||||
/// `com.android.support:support-annotations:+` dependency can be built as AAR.
|
/// `com.android.support:support-annotations:+` dependency can be built as AAR.
|
||||||
@ -60,6 +60,12 @@ Future<void> main() async {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
section('Update proguard rules');
|
||||||
|
|
||||||
|
// Don't obfuscate the input class files, since the test is checking if some classes are in the DEX.
|
||||||
|
final File proguardRules = File(path.join(projectDir.path, 'android', 'app', 'proguard-rules.pro'));
|
||||||
|
proguardRules.writeAsStringSync('-dontobfuscate', flush: true);
|
||||||
|
|
||||||
section('Build release APK');
|
section('Build release APK');
|
||||||
|
|
||||||
await inDirectory(projectDir, () async {
|
await inDirectory(projectDir, () async {
|
||||||
|
@ -11,7 +11,7 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
final bool useAndroidEmbeddingV2 = Platform.environment['ENABLE_ANDROID_EMBEDDING_V2'] == 'true';
|
final bool useAndroidEmbeddingV2 = Platform.environment['ENABLE_ANDROID_EMBEDDING_V2'] == 'true';
|
||||||
|
|
||||||
@ -125,9 +125,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...debugAssets,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], await getFilesInApk(demoDebugApk));
|
], await getFilesInApk(demoDebugApk));
|
||||||
|
|
||||||
await clean();
|
await clean();
|
||||||
@ -170,9 +168,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...debugAssets,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], await getFilesInApk(demoDebugApk2));
|
], await getFilesInApk(demoDebugApk2));
|
||||||
|
|
||||||
await clean();
|
await clean();
|
||||||
@ -207,9 +203,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...debugAssets,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], await getFilesInApk(demoStagingApk));
|
], await getFilesInApk(demoStagingApk));
|
||||||
|
|
||||||
await clean();
|
await clean();
|
||||||
@ -246,10 +240,10 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'lib/arm64-v8a/libapp.so',
|
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
'lib/armeabi-v7a/libflutter.so',
|
'lib/armeabi-v7a/libflutter.so',
|
||||||
|
'lib/armeabi-v7a/libapp.so',
|
||||||
], await getFilesInApk(demoReleaseApk));
|
], await getFilesInApk(demoReleaseApk));
|
||||||
|
|
||||||
await clean();
|
await clean();
|
||||||
|
@ -11,14 +11,13 @@ import 'package:flutter_devicelab/framework/utils.dart';
|
|||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
final String gradlew = Platform.isWindows ? 'gradlew.bat' : 'gradlew';
|
||||||
final String gradlewExecutable = Platform.isWindows ? gradlew : './$gradlew';
|
final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradlew';
|
||||||
|
|
||||||
final bool useAndroidEmbeddingV2 = Platform.environment['ENABLE_ANDROID_EMBEDDING_V2'] == 'true';
|
final bool useAndroidEmbeddingV2 = Platform.environment['ENABLE_ANDROID_EMBEDDING_V2'] == 'true';
|
||||||
|
|
||||||
/// Tests that the Flutter module project template works and supports
|
/// Tests that the Flutter module project template works and supports
|
||||||
/// adding Flutter to an existing Android app.
|
/// adding Flutter to an existing Android app.
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
print(useAndroidEmbeddingV2);
|
|
||||||
await task(() async {
|
await task(() async {
|
||||||
|
|
||||||
section('Find Java');
|
section('Find Java');
|
||||||
@ -201,10 +200,8 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'AndroidManifest.xml',
|
...debugAssets,
|
||||||
'assets/flutter_assets/isolate_snapshot_data',
|
...baseApkFiles,
|
||||||
'assets/flutter_assets/kernel_blob.bin',
|
|
||||||
'assets/flutter_assets/vm_snapshot_data',
|
|
||||||
], await getFilesInApk(debugHostApk));
|
], await getFilesInApk(debugHostApk));
|
||||||
|
|
||||||
section('Check debug AndroidManifest.xml');
|
section('Check debug AndroidManifest.xml');
|
||||||
@ -258,7 +255,7 @@ Future<void> main() async {
|
|||||||
|
|
||||||
checkItContains<String>(<String>[
|
checkItContains<String>(<String>[
|
||||||
...flutterAssets,
|
...flutterAssets,
|
||||||
'AndroidManifest.xml',
|
...baseApkFiles,
|
||||||
'lib/arm64-v8a/libapp.so',
|
'lib/arm64-v8a/libapp.so',
|
||||||
'lib/arm64-v8a/libflutter.so',
|
'lib/arm64-v8a/libflutter.so',
|
||||||
'lib/armeabi-v7a/libapp.so',
|
'lib/armeabi-v7a/libapp.so',
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
@ -17,6 +16,17 @@ final List<String> flutterAssets = <String>[
|
|||||||
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
'assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
final List<String> debugAssets = <String>[
|
||||||
|
'assets/flutter_assets/isolate_snapshot_data',
|
||||||
|
'assets/flutter_assets/kernel_blob.bin',
|
||||||
|
'assets/flutter_assets/vm_snapshot_data',
|
||||||
|
];
|
||||||
|
|
||||||
|
final List<String> baseApkFiles = <String> [
|
||||||
|
'classes.dex',
|
||||||
|
'AndroidManifest.xml',
|
||||||
|
];
|
||||||
|
|
||||||
/// Runs the given [testFunction] on a freshly generated Flutter project.
|
/// Runs the given [testFunction] on a freshly generated Flutter project.
|
||||||
Future<void> runProjectTest(Future<void> testFunction(FlutterProject project)) async {
|
Future<void> runProjectTest(Future<void> testFunction(FlutterProject project)) async {
|
||||||
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_devicelab_gradle_plugin_test.');
|
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_devicelab_gradle_plugin_test.');
|
||||||
@ -43,20 +53,18 @@ Future<void> runPluginProjectTest(Future<void> testFunction(FlutterPluginProject
|
|||||||
|
|
||||||
/// Returns the list of files inside an Android Package Kit.
|
/// Returns the list of files inside an Android Package Kit.
|
||||||
Future<Iterable<String>> getFilesInApk(String apk) async {
|
Future<Iterable<String>> getFilesInApk(String apk) async {
|
||||||
if (!File(apk).existsSync())
|
if (!File(apk).existsSync()) {
|
||||||
throw TaskResult.failure(
|
throw TaskResult.failure(
|
||||||
'Gradle did not produce an output artifact file at: $apk');
|
'Gradle did not produce an output artifact file at: $apk');
|
||||||
|
}
|
||||||
final Process unzip = await startProcess(
|
final String files = await _evalApkAnalyzer(
|
||||||
'unzip',
|
<String>[
|
||||||
<String>['-v', apk],
|
'files',
|
||||||
isBot: false, // we just want to test the output, not have any debugging info
|
'list',
|
||||||
|
apk,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
return unzip.stdout
|
return files.split('\n').map((String file) => file.substring(1).trim());
|
||||||
.transform(utf8.decoder)
|
|
||||||
.transform(const LineSplitter())
|
|
||||||
.map((String line) => line.split(' ').last)
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
/// Returns the list of files inside an Android App Bundle.
|
/// Returns the list of files inside an Android App Bundle.
|
||||||
Future<Iterable<String>> getFilesInAppBundle(String bundle) {
|
Future<Iterable<String>> getFilesInAppBundle(String bundle) {
|
||||||
@ -71,7 +79,7 @@ Future<Iterable<String>> getFilesInAar(String aar) {
|
|||||||
void checkItContains<T>(Iterable<T> values, Iterable<T> collection) {
|
void checkItContains<T>(Iterable<T> values, Iterable<T> collection) {
|
||||||
for (T value in values) {
|
for (T value in values) {
|
||||||
if (!collection.contains(value)) {
|
if (!collection.contains(value)) {
|
||||||
throw TaskResult.failure('Expected to find `$value` in `$collection`.');
|
throw TaskResult.failure('Expected to find `$value` in `${collection.toString()}`.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,9 +128,36 @@ String get _androidHome {
|
|||||||
return androidHome;
|
return androidHome;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility class to analyze the content inside an APK using dexdump,
|
/// Executes an APK analyzer subcommand.
|
||||||
/// which is provided by the Android SDK.
|
Future<String> _evalApkAnalyzer(
|
||||||
/// https://android.googlesource.com/platform/art/+/master/dexdump/dexdump.cc
|
List<String> args, {
|
||||||
|
bool printStdout = true,
|
||||||
|
String workingDirectory,
|
||||||
|
}) async {
|
||||||
|
final String javaHome = await findJavaHome();
|
||||||
|
final String javaBinary = path.join(javaHome, 'bin', 'java');
|
||||||
|
assert(canRun(javaBinary));
|
||||||
|
|
||||||
|
final String androidTools = path.join(_androidHome, 'tools');
|
||||||
|
final String libs = path.join(androidTools, 'lib');
|
||||||
|
assert(Directory(libs).existsSync());
|
||||||
|
|
||||||
|
final String classSeparator = Platform.isWindows ? ';' : ':';
|
||||||
|
return eval(
|
||||||
|
javaBinary,
|
||||||
|
<String>[
|
||||||
|
'-Dcom.android.sdklib.toolsdir=$androidTools',
|
||||||
|
'-classpath',
|
||||||
|
'.$classSeparator$libs${Platform.pathSeparator}*',
|
||||||
|
'com.android.tools.apk.analyzer.ApkAnalyzerCli',
|
||||||
|
...args,
|
||||||
|
],
|
||||||
|
printStdout: printStdout,
|
||||||
|
workingDirectory: workingDirectory,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Utility class to analyze the content inside an APK using the APK analyzer.
|
||||||
class ApkExtractor {
|
class ApkExtractor {
|
||||||
ApkExtractor(this.apkFile);
|
ApkExtractor(this.apkFile);
|
||||||
|
|
||||||
@ -131,70 +166,56 @@ class ApkExtractor {
|
|||||||
|
|
||||||
bool _extracted = false;
|
bool _extracted = false;
|
||||||
|
|
||||||
Directory _outputDir;
|
Set<String> _classes = const <String>{};
|
||||||
|
|
||||||
Future<void> _extractApk() async {
|
Future<void> _extractDex() async {
|
||||||
if (_extracted) {
|
if (_extracted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_outputDir = apkFile.parent.createTempSync('apk');
|
final String packages = await _evalApkAnalyzer(
|
||||||
if (Platform.isWindows) {
|
<String>[
|
||||||
await eval('7za', <String>['x', apkFile.path], workingDirectory: _outputDir.path);
|
'dex',
|
||||||
} else {
|
'packages',
|
||||||
await eval('unzip', <String>[apkFile.path], workingDirectory: _outputDir.path);
|
apkFile.path,
|
||||||
}
|
],
|
||||||
|
printStdout: false,
|
||||||
|
);
|
||||||
|
_classes = Set<String>.from(
|
||||||
|
packages
|
||||||
|
.split('\n')
|
||||||
|
.where((String line) => line.startsWith('C'))
|
||||||
|
.map<String>((String line) => line.split('\t').last),
|
||||||
|
);
|
||||||
|
assert(_classes.isNotEmpty);
|
||||||
_extracted = true;
|
_extracted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the full path to the [dexdump] tool.
|
|
||||||
Future<String> _findDexDump() async {
|
|
||||||
String dexdumps;
|
|
||||||
if (Platform.isWindows) {
|
|
||||||
dexdumps = await eval('dir', <String>['/s/b', 'dexdump.exe'],
|
|
||||||
workingDirectory: _androidHome);
|
|
||||||
} else {
|
|
||||||
dexdumps = await eval('find', <String>[_androidHome, '-name', 'dexdump']);
|
|
||||||
}
|
|
||||||
if (dexdumps.isEmpty) {
|
|
||||||
throw Exception('Couldn\'t find a dexdump executable.');
|
|
||||||
}
|
|
||||||
return dexdumps.split('\n').first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes any temporary directory.
|
// Removes any temporary directory.
|
||||||
void dispose() {
|
void dispose() {
|
||||||
if (!_extracted) {
|
if (!_extracted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rmTree(_outputDir);
|
_classes = const <String>{};
|
||||||
_extracted = true;
|
_extracted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the APK contains a given class.
|
/// Returns true if the APK contains a given class.
|
||||||
Future<bool> containsClass(String className) async {
|
Future<bool> containsClass(String className) async {
|
||||||
await _extractApk();
|
await _extractDex();
|
||||||
|
return _classes.contains(className);
|
||||||
final String dexDump = await _findDexDump();
|
|
||||||
final String classesDex = path.join(_outputDir.path, 'classes.dex');
|
|
||||||
|
|
||||||
if (!File(classesDex).existsSync()) {
|
|
||||||
throw Exception('Couldn\'t find classes.dex in the APK.');
|
|
||||||
}
|
|
||||||
final String classDescriptors = await eval(dexDump,
|
|
||||||
<String>[classesDex], printStdout: false);
|
|
||||||
|
|
||||||
if (classDescriptors.isEmpty) {
|
|
||||||
throw Exception('No descriptors found in classes.dex.');
|
|
||||||
}
|
|
||||||
return classDescriptors.contains(className.replaceAll('.', '/'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the content of the `AndroidManifest.xml`.
|
/// Gets the content of the `AndroidManifest.xml`.
|
||||||
Future<String> getAndroidManifest(String apk) {
|
Future<String> getAndroidManifest(String apk) async {
|
||||||
final String apkAnalyzer = path.join(_androidHome, 'tools', 'bin', 'apkanalyzer');
|
return await _evalApkAnalyzer(
|
||||||
return eval(apkAnalyzer, <String>['manifest', 'print', apk],
|
<String>[
|
||||||
workingDirectory: _androidHome);
|
'manifest',
|
||||||
|
'print',
|
||||||
|
apk,
|
||||||
|
],
|
||||||
|
workingDirectory: _androidHome,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that the classes are contained in the APK, throws otherwise.
|
/// Checks that the classes are contained in the APK, throws otherwise.
|
||||||
@ -318,7 +339,7 @@ android {
|
|||||||
|
|
||||||
Future<ProcessResult> resultOfFlutterCommand(String command, List<String> options) {
|
Future<ProcessResult> resultOfFlutterCommand(String command, List<String> options) {
|
||||||
return Process.run(
|
return Process.run(
|
||||||
path.join(flutterDirectory.path, 'bin', 'flutter'),
|
path.join(flutterDirectory.path, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter'),
|
||||||
<String>[command, ...options],
|
<String>[command, ...options],
|
||||||
workingDirectory: rootPath,
|
workingDirectory: rootPath,
|
||||||
);
|
);
|
||||||
@ -401,39 +422,14 @@ Future<ProcessResult> _resultOfGradleTask({String workingDirectory, String task,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Dependencies {
|
|
||||||
_Dependencies(String depfilePath) {
|
|
||||||
// Depfile format:
|
|
||||||
// outfile1 outfile2 : file1.dart file2.dart file3.dart file\ 4.dart
|
|
||||||
final String contents = File(depfilePath).readAsStringSync();
|
|
||||||
final List<String> colonSeparated = contents.split(':');
|
|
||||||
targets = _processList(colonSeparated[0].trim());
|
|
||||||
dependencies = _processList(colonSeparated[1].trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
final RegExp _separatorExpr = RegExp(r'([^\\]) ');
|
|
||||||
final RegExp _escapeExpr = RegExp(r'\\(.)');
|
|
||||||
|
|
||||||
Set<String> _processList(String rawText) {
|
|
||||||
return rawText
|
|
||||||
// Put every file on right-hand side on the separate line
|
|
||||||
.replaceAllMapped(_separatorExpr, (Match match) => '${match.group(1)}\n')
|
|
||||||
.split('\n')
|
|
||||||
// Expand escape sequences, so that '\ ', for example,ß becomes ' '
|
|
||||||
.map<String>((String path) => path.replaceAllMapped(_escapeExpr, (Match match) => match.group(1)).trim())
|
|
||||||
.where((String path) => path.isNotEmpty)
|
|
||||||
.toSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<String> targets;
|
|
||||||
Set<String> dependencies;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns [null] if target matches [expectedTarget], otherwise returns an error message.
|
/// Returns [null] if target matches [expectedTarget], otherwise returns an error message.
|
||||||
String validateSnapshotDependency(FlutterProject project, String expectedTarget) {
|
String validateSnapshotDependency(FlutterProject project, String expectedTarget) {
|
||||||
final _Dependencies deps = _Dependencies(
|
final File snapshotBlob = File(
|
||||||
path.join(project.rootPath, 'build', 'app', 'intermediates',
|
path.join(project.rootPath, 'build', 'app', 'intermediates',
|
||||||
'flutter', 'debug', 'android-arm', 'snapshot_blob.bin.d'));
|
'flutter', 'debug', 'android-arm', 'snapshot_blob.bin.d'));
|
||||||
return deps.targets.any((String target) => target.contains(expectedTarget)) ? null :
|
|
||||||
'Dependency file should have $expectedTarget as target. Instead has ${deps.targets}';
|
assert(snapshotBlob.existsSync());
|
||||||
|
final String contentSnapshot = snapshotBlob.readAsStringSync();
|
||||||
|
return contentSnapshot.contains('$expectedTarget ')
|
||||||
|
? null : 'Dependency file should have $expectedTarget as target. Instead found $contentSnapshot';
|
||||||
}
|
}
|
||||||
|
@ -255,13 +255,14 @@ Future<Process> startProcess(
|
|||||||
}) async {
|
}) async {
|
||||||
assert(isBot != null);
|
assert(isBot != null);
|
||||||
final String command = '$executable ${arguments?.join(" ") ?? ""}';
|
final String command = '$executable ${arguments?.join(" ") ?? ""}';
|
||||||
print('\nExecuting: $command');
|
final String finalWorkingDirectory = workingDirectory ?? cwd;
|
||||||
|
print('\nExecuting: $command in $finalWorkingDirectory');
|
||||||
environment ??= <String, String>{};
|
environment ??= <String, String>{};
|
||||||
environment['BOT'] = isBot ? 'true' : 'false';
|
environment['BOT'] = isBot ? 'true' : 'false';
|
||||||
final Process process = await _processManager.start(
|
final Process process = await _processManager.start(
|
||||||
<String>[executable, ...arguments],
|
<String>[executable, ...arguments],
|
||||||
environment: environment,
|
environment: environment,
|
||||||
workingDirectory: workingDirectory ?? cwd,
|
workingDirectory: finalWorkingDirectory,
|
||||||
);
|
);
|
||||||
final ProcessInfo processInfo = ProcessInfo(command, process);
|
final ProcessInfo processInfo = ProcessInfo(command, process);
|
||||||
_runningProcesses.add(processInfo);
|
_runningProcesses.add(processInfo);
|
||||||
@ -447,7 +448,7 @@ void cd(dynamic directory) {
|
|||||||
throw 'Cannot cd into directory that does not exist: $directory';
|
throw 'Cannot cd into directory that does not exist: $directory';
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory get flutterDirectory => dir('../..').absolute;
|
Directory get flutterDirectory => Directory.current.parent.parent;
|
||||||
|
|
||||||
String requireEnvVar(String name) {
|
String requireEnvVar(String name) {
|
||||||
final String value = Platform.environment[name];
|
final String value = Platform.environment[name];
|
||||||
|
Loading…
Reference in New Issue
Block a user