Unverified Commit d9c19629 authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Instrument usage of include_flutter.groovy and xcode_backend.sh (#34189)

This is done via `flutter build bundle`.   As a consequence, this PR introduces a new way to disable analytics via the `FLUTTER_SUPPRESS_ANALYTICS` env flag.
parent 1eb8c640
...@@ -249,7 +249,7 @@ BuildApp() { ...@@ -249,7 +249,7 @@ BuildApp() {
fi fi
StreamOutput " ├─Assembling Flutter resources..." StreamOutput " ├─Assembling Flutter resources..."
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \ RunCommand "${FLUTTER_ROOT}/bin/flutter" \
${verbose_flag} \ ${verbose_flag} \
build bundle \ build bundle \
--target-platform=ios \ --target-platform=ios \
......
...@@ -717,7 +717,6 @@ abstract class BaseFlutterTask extends DefaultTask { ...@@ -717,7 +717,6 @@ abstract class BaseFlutterTask extends DefaultTask {
args "--local-engine-src-path", localEngineSrcPath args "--local-engine-src-path", localEngineSrcPath
} }
args "build", "bundle" args "build", "bundle"
args "--suppress-analytics"
args "--target", targetPath args "--target", targetPath
args "--target-platform", "${targetPlatform}" args "--target-platform", "${targetPlatform}"
if (verbose) { if (verbose) {
......
...@@ -601,6 +601,10 @@ Map<String, String> get _gradleEnv { ...@@ -601,6 +601,10 @@ Map<String, String> get _gradleEnv {
// Use java bundled with Android Studio. // Use java bundled with Android Studio.
env['JAVA_HOME'] = javaPath; env['JAVA_HOME'] = javaPath;
} }
// Don't log analytics for downstream Flutter commands.
// e.g. `flutter build bundle`.
env['FLUTTER_SUPPRESS_ANALYTICS'] = 'true';
return env; return env;
} }
......
...@@ -48,114 +48,121 @@ const String _kVMSnapshotData = 'vm_snapshot_data'; ...@@ -48,114 +48,121 @@ const String _kVMSnapshotData = 'vm_snapshot_data';
const String _kIsolateSnapshotData = 'isolate_snapshot_data'; const String _kIsolateSnapshotData = 'isolate_snapshot_data';
const String _kIsolateSnapshotInstr = 'isolate_snapshot_instr'; const String _kIsolateSnapshotInstr = 'isolate_snapshot_instr';
Future<void> build({ /// Provides a `build` method that builds the bundle.
TargetPlatform platform, class BundleBuilder {
BuildMode buildMode, /// Builds the bundle for the given target platform.
String mainPath = defaultMainPath, ///
String manifestPath = defaultManifestPath, /// The default `mainPath` is `lib/main.dart`.
String applicationKernelFilePath, /// The default `manifestPath` is `pubspec.yaml`
String depfilePath, Future<void> build({
String privateKeyPath = defaultPrivateKeyPath, TargetPlatform platform,
String assetDirPath, BuildMode buildMode,
String packagesPath, String mainPath = defaultMainPath,
bool precompiledSnapshot = false, String manifestPath = defaultManifestPath,
bool reportLicensedPackages = false, String applicationKernelFilePath,
bool trackWidgetCreation = false, String depfilePath,
String compilationTraceFilePath, String privateKeyPath = defaultPrivateKeyPath,
List<String> extraFrontEndOptions = const <String>[], String assetDirPath,
List<String> extraGenSnapshotOptions = const <String>[], String packagesPath,
List<String> fileSystemRoots, bool precompiledSnapshot = false,
String fileSystemScheme, bool reportLicensedPackages = false,
}) async { bool trackWidgetCreation = false,
depfilePath ??= defaultDepfilePath; String compilationTraceFilePath,
assetDirPath ??= getAssetBuildDirectory(); List<String> extraFrontEndOptions = const <String>[],
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath); List<String> extraGenSnapshotOptions = const <String>[],
applicationKernelFilePath ??= getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation); List<String> fileSystemRoots,
final FlutterProject flutterProject = FlutterProject.current(); String fileSystemScheme,
}) async {
depfilePath ??= defaultDepfilePath;
assetDirPath ??= getAssetBuildDirectory();
packagesPath ??= fs.path.absolute(PackageMap.globalPackagesPath);
applicationKernelFilePath ??= getDefaultApplicationKernelPath(trackWidgetCreation: trackWidgetCreation);
final FlutterProject flutterProject = FlutterProject.current();
if (compilationTraceFilePath != null) { if (compilationTraceFilePath != null) {
if (buildMode != BuildMode.dynamicProfile && buildMode != BuildMode.dynamicRelease) { if (buildMode != BuildMode.dynamicProfile && buildMode != BuildMode.dynamicRelease) {
// Silently ignore JIT snapshotting for those builds that don't support it. // Silently ignore JIT snapshotting for those builds that don't support it.
compilationTraceFilePath = null; compilationTraceFilePath = null;
} else if (compilationTraceFilePath.isEmpty) { } else if (compilationTraceFilePath.isEmpty) {
// Disable JIT snapshotting if flag is empty. // Disable JIT snapshotting if flag is empty.
printStatus('Code snapshot will be disabled for this build.'); printStatus('Code snapshot will be disabled for this build.');
compilationTraceFilePath = null; compilationTraceFilePath = null;
} else if (!fs.file(compilationTraceFilePath).existsSync()) { } else if (!fs.file(compilationTraceFilePath).existsSync()) {
// Be forgiving if compilation trace file is missing. // Be forgiving if compilation trace file is missing.
printStatus('No compilation trace available. To optimize performance, consider using --train.'); printStatus('No compilation trace available. To optimize performance, consider using --train.');
final File tmp = fs.systemTempDirectory.childFile('flutterEmptyCompilationTrace.txt'); final File tmp = fs.systemTempDirectory.childFile('flutterEmptyCompilationTrace.txt');
compilationTraceFilePath = (tmp..createSync(recursive: true)).path; compilationTraceFilePath = (tmp..createSync(recursive: true)).path;
} else { } else {
printStatus('Code snapshot will use compilation training file $compilationTraceFilePath.'); printStatus('Code snapshot will use compilation training file $compilationTraceFilePath.');
} }
}
DevFSContent kernelContent;
if (!precompiledSnapshot) {
if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
printTrace('Extra front-end options: $extraFrontEndOptions');
ensureDirectoryExists(applicationKernelFilePath);
final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(flutterProject);
final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath, mode: buildMode),
incrementalCompilerByteStorePath: compilationTraceFilePath != null ? null :
fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
mainPath: fs.file(mainPath).absolute.path,
outputFilePath: applicationKernelFilePath,
depFilePath: depfilePath,
trackWidgetCreation: trackWidgetCreation,
extraFrontEndOptions: extraFrontEndOptions,
fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme,
packagesPath: packagesPath,
linkPlatformKernelIn: compilationTraceFilePath != null,
);
if (compilerOutput?.outputFilename == null) {
throwToolExit('Compiler failed on $mainPath');
} }
kernelContent = DevFSFileContent(fs.file(compilerOutput.outputFilename));
await fs.directory(getBuildDirectory()).childFile('frontend_server.d')
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
if (compilationTraceFilePath != null) { DevFSContent kernelContent;
final JITSnapshotter snapshotter = JITSnapshotter(); if (!precompiledSnapshot) {
final int snapshotExitCode = await snapshotter.build( if ((extraFrontEndOptions != null) && extraFrontEndOptions.isNotEmpty)
platform: platform, printTrace('Extra front-end options: $extraFrontEndOptions');
buildMode: buildMode, ensureDirectoryExists(applicationKernelFilePath);
mainPath: applicationKernelFilePath, final KernelCompiler kernelCompiler = await kernelCompilerFactory.create(flutterProject);
outputPath: getBuildDirectory(), final CompilerOutput compilerOutput = await kernelCompiler.compile(
sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath, mode: buildMode),
incrementalCompilerByteStorePath: compilationTraceFilePath != null ? null :
fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
mainPath: fs.file(mainPath).absolute.path,
outputFilePath: applicationKernelFilePath,
depFilePath: depfilePath,
trackWidgetCreation: trackWidgetCreation,
extraFrontEndOptions: extraFrontEndOptions,
fileSystemRoots: fileSystemRoots,
fileSystemScheme: fileSystemScheme,
packagesPath: packagesPath, packagesPath: packagesPath,
compilationTraceFilePath: compilationTraceFilePath, linkPlatformKernelIn: compilationTraceFilePath != null,
extraGenSnapshotOptions: extraGenSnapshotOptions,
); );
if (snapshotExitCode != 0) { if (compilerOutput?.outputFilename == null) {
throwToolExit('Snapshotting exited with non-zero exit code: $snapshotExitCode'); throwToolExit('Compiler failed on $mainPath');
}
kernelContent = DevFSFileContent(fs.file(compilerOutput.outputFilename));
await fs.directory(getBuildDirectory()).childFile('frontend_server.d')
.writeAsString('frontend_server.d: ${artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk)}\n');
if (compilationTraceFilePath != null) {
final JITSnapshotter snapshotter = JITSnapshotter();
final int snapshotExitCode = await snapshotter.build(
platform: platform,
buildMode: buildMode,
mainPath: applicationKernelFilePath,
outputPath: getBuildDirectory(),
packagesPath: packagesPath,
compilationTraceFilePath: compilationTraceFilePath,
extraGenSnapshotOptions: extraGenSnapshotOptions,
);
if (snapshotExitCode != 0) {
throwToolExit('Snapshotting exited with non-zero exit code: $snapshotExitCode');
}
} }
} }
}
final AssetBundle assets = await buildAssets( final AssetBundle assets = await buildAssets(
manifestPath: manifestPath, manifestPath: manifestPath,
assetDirPath: assetDirPath, assetDirPath: assetDirPath,
packagesPath: packagesPath, packagesPath: packagesPath,
reportLicensedPackages: reportLicensedPackages, reportLicensedPackages: reportLicensedPackages,
); );
if (assets == null) if (assets == null)
throwToolExit('Error building assets', exitCode: 1); throwToolExit('Error building assets', exitCode: 1);
await assemble( await assemble(
buildMode: buildMode, buildMode: buildMode,
assetBundle: assets, assetBundle: assets,
kernelContent: kernelContent, kernelContent: kernelContent,
privateKeyPath: privateKeyPath, privateKeyPath: privateKeyPath,
assetDirPath: assetDirPath, assetDirPath: assetDirPath,
compilationTraceFilePath: compilationTraceFilePath, compilationTraceFilePath: compilationTraceFilePath,
); );
}
} }
Future<AssetBundle> buildAssets({ Future<AssetBundle> buildAssets({
......
...@@ -5,14 +5,17 @@ ...@@ -5,14 +5,17 @@
import 'dart:async'; import 'dart:async';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart'; import '../bundle.dart';
import '../project.dart';
import '../runner/flutter_command.dart' show FlutterOptions, FlutterCommandResult; import '../runner/flutter_command.dart' show FlutterOptions, FlutterCommandResult;
import '../usage.dart';
import '../version.dart'; import '../version.dart';
import 'build.dart'; import 'build.dart';
class BuildBundleCommand extends BuildSubCommand { class BuildBundleCommand extends BuildSubCommand {
BuildBundleCommand({bool verboseHelp = false}) { BuildBundleCommand({bool verboseHelp = false, this.bundleBuilder}) {
usesTargetOption(); usesTargetOption();
usesFilesystemOptions(hide: !verboseHelp); usesFilesystemOptions(hide: !verboseHelp);
usesBuildNumberOption(); usesBuildNumberOption();
...@@ -57,8 +60,12 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -57,8 +60,12 @@ class BuildBundleCommand extends BuildSubCommand {
'in the application\'s LICENSE file.', 'in the application\'s LICENSE file.',
defaultsTo: false); defaultsTo: false);
usesPubOption(); usesPubOption();
bundleBuilder ??= BundleBuilder();
} }
BundleBuilder bundleBuilder;
@override @override
final String name = 'bundle'; final String name = 'bundle';
...@@ -70,6 +77,21 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -70,6 +77,21 @@ class BuildBundleCommand extends BuildSubCommand {
'application code and resources; they are used by some Flutter Android and' 'application code and resources; they are used by some Flutter Android and'
' iOS runtimes.'; ' iOS runtimes.';
@override
Future<Map<String, String>> get usageValues async {
final String projectDir = fs.file(targetFile).parent.parent.path;
final FlutterProject futterProject = FlutterProject.fromPath(projectDir);
if (futterProject == null) {
return const <String, String>{};
}
return <String, String>{
kCommandBuildBundleTargetPlatform: argResults['target-platform'],
kCommandBuildBundleIsModule: '${futterProject.isModule}'
};
}
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
final String targetPlatform = argResults['target-platform']; final String targetPlatform = argResults['target-platform'];
...@@ -92,7 +114,7 @@ class BuildBundleCommand extends BuildSubCommand { ...@@ -92,7 +114,7 @@ class BuildBundleCommand extends BuildSubCommand {
final BuildMode buildMode = getBuildMode(); final BuildMode buildMode = getBuildMode();
await build( await bundleBuilder.build(
platform: platform, platform: platform,
buildMode: buildMode, buildMode: buildMode,
mainPath: targetFile, mainPath: targetFile,
......
...@@ -279,6 +279,10 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -279,6 +279,10 @@ Future<XcodeBuildResult> buildXcodeProject({
buildCommands.add('SCRIPT_OUTPUT_STREAM_FILE=${scriptOutputPipeFile.absolute.path}'); buildCommands.add('SCRIPT_OUTPUT_STREAM_FILE=${scriptOutputPipeFile.absolute.path}');
} }
// Don't log analytics for downstream Flutter commands.
// e.g. `flutter build bundle`.
buildCommands.add('FLUTTER_SUPPRESS_ANALYTICS=true');
final Stopwatch sw = Stopwatch()..start(); final Stopwatch sw = Stopwatch()..start();
initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation); initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
final RunResult buildResult = await runAsync( final RunResult buildResult = await runAsync(
......
...@@ -15,7 +15,7 @@ import '../base/process.dart'; ...@@ -15,7 +15,7 @@ import '../base/process.dart';
import '../base/process_manager.dart'; import '../base/process_manager.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart' as bundle; import '../bundle.dart';
import '../convert.dart'; import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
...@@ -412,7 +412,7 @@ class IOSSimulator extends Device { ...@@ -412,7 +412,7 @@ class IOSSimulator extends Device {
Future<void> _sideloadUpdatedAssetsForInstalledApplicationBundle(ApplicationPackage app, BuildInfo buildInfo, String mainPath) { Future<void> _sideloadUpdatedAssetsForInstalledApplicationBundle(ApplicationPackage app, BuildInfo buildInfo, String mainPath) {
// Run compiler to produce kernel file for the application. // Run compiler to produce kernel file for the application.
return bundle.build( return BundleBuilder().build(
mainPath: mainPath, mainPath: mainPath,
precompiledSnapshot: false, precompiledSnapshot: false,
trackWidgetCreation: buildInfo.trackWidgetCreation, trackWidgetCreation: buildInfo.trackWidgetCreation,
......
...@@ -13,7 +13,7 @@ import '../base/file_system.dart'; ...@@ -13,7 +13,7 @@ import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/process_manager.dart'; import '../base/process_manager.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../bundle.dart' as bundle; import '../bundle.dart';
import '../convert.dart'; import '../convert.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
import '../device.dart'; import '../device.dart';
...@@ -129,11 +129,11 @@ class FlutterTesterDevice extends Device { ...@@ -129,11 +129,11 @@ class FlutterTesterDevice extends Device {
// Build assets and perform initial compilation. // Build assets and perform initial compilation.
final String assetDirPath = getAssetBuildDirectory(); final String assetDirPath = getAssetBuildDirectory();
final String applicationKernelFilePath = bundle.getKernelPathForTransformerOptions( final String applicationKernelFilePath = getKernelPathForTransformerOptions(
fs.path.join(getBuildDirectory(), 'flutter-tester-app.dill'), fs.path.join(getBuildDirectory(), 'flutter-tester-app.dill'),
trackWidgetCreation: buildInfo.trackWidgetCreation, trackWidgetCreation: buildInfo.trackWidgetCreation,
); );
await bundle.build( await BundleBuilder().build(
mainPath: mainPath, mainPath: mainPath,
assetDirPath: assetDirPath, assetDirPath: assetDirPath,
applicationKernelFilePath: applicationKernelFilePath, applicationKernelFilePath: applicationKernelFilePath,
......
...@@ -45,6 +45,10 @@ const String kCommandCreateProjectType = 'cd19'; ...@@ -45,6 +45,10 @@ const String kCommandCreateProjectType = 'cd19';
const String kCommandPackagesNumberPlugins = 'cd20'; const String kCommandPackagesNumberPlugins = 'cd20';
const String kCommandPackagesProjectModule = 'cd21'; const String kCommandPackagesProjectModule = 'cd21';
const String kCommandBuildBundleTargetPlatform = 'cd24';
const String kCommandBuildBundleIsModule = 'cd25';
// Next ID: cd26
Usage get flutterUsage => Usage.instance; Usage get flutterUsage => Usage.instance;
class Usage { class Usage {
...@@ -66,8 +70,9 @@ class Usage { ...@@ -66,8 +70,9 @@ class Usage {
} }
_analytics.analyticsOpt = AnalyticsOpt.optOut; _analytics.analyticsOpt = AnalyticsOpt.optOut;
final bool suppressEnvFlag = platform.environment['FLUTTER_SUPPRESS_ANALYTICS'] == 'true';
// Many CI systems don't do a full git checkout. // Many CI systems don't do a full git checkout.
if (version.endsWith('/unknown') || isRunningOnBot) { if (version.endsWith('/unknown') || isRunningOnBot || suppressEnvFlag) {
// If we think we're running on a CI system, suppress sending analytics. // If we think we're running on a CI system, suppress sending analytics.
suppressAnalytics = true; suppressAnalytics = true;
} }
......
// Copyright 2019 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 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/build_bundle.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/usage.dart';
import 'package:mockito/mockito.dart';
import '../src/common.dart';
import '../src/context.dart';
void main() {
Cache.disableLocking();
group('getUsage', () {
Directory tempDir;
MockBundleBuilder mockBundleBuilder;
setUp(() {
tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_packages_test.');
mockBundleBuilder = MockBundleBuilder();
when(
mockBundleBuilder.build(
platform: anyNamed('platform'),
buildMode: anyNamed('buildMode'),
mainPath: anyNamed('mainPath'),
manifestPath: anyNamed('manifestPath'),
applicationKernelFilePath: anyNamed('applicationKernelFilePath'),
depfilePath: anyNamed('depfilePath'),
privateKeyPath: anyNamed('privateKeyPath'),
assetDirPath: anyNamed('assetDirPath'),
packagesPath: anyNamed('packagesPath'),
precompiledSnapshot: anyNamed('precompiledSnapshot'),
reportLicensedPackages: anyNamed('reportLicensedPackages'),
trackWidgetCreation: anyNamed('trackWidgetCreation'),
compilationTraceFilePath: anyNamed('compilationTraceFilePath'),
extraFrontEndOptions: anyNamed('extraFrontEndOptions'),
extraGenSnapshotOptions: anyNamed('extraGenSnapshotOptions'),
fileSystemRoots: anyNamed('fileSystemRoots'),
fileSystemScheme: anyNamed('fileSystemScheme'),
),
).thenAnswer((_) => Future<void>.value());
});
tearDown(() {
tryToDelete(tempDir);
});
Future<BuildBundleCommand> runCommandIn(String projectPath, { List<String> arguments }) async {
final BuildBundleCommand command = BuildBundleCommand(bundleBuilder: mockBundleBuilder);
final CommandRunner<void> runner = createTestCommandRunner(command);
final List<String> commandArgs = <String>['bundle'];
if (arguments != null)
commandArgs.addAll(arguments);
commandArgs.add('--target=$projectPath/lib/main.dart');
await runner.run(commandArgs);
return command;
}
testUsingContext('indicate that project is a module', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=module']);
final BuildBundleCommand command = await runCommandIn(projectPath);
expect(await command.usageValues,
containsPair(kCommandBuildBundleIsModule, 'true'));
}, timeout: allowForCreateFlutterProject);
testUsingContext('indicate that project is not a module', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
final BuildBundleCommand command = await runCommandIn(projectPath);
expect(await command.usageValues,
containsPair(kCommandBuildBundleIsModule, 'false'));
}, timeout: allowForCreateFlutterProject);
testUsingContext('indicate the target platform', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
final BuildBundleCommand command = await runCommandIn(projectPath);
expect(await command.usageValues,
containsPair(kCommandBuildBundleTargetPlatform, 'android-arm'));
}, timeout: allowForCreateFlutterProject);
});
}
class MockBundleBuilder extends Mock implements BundleBuilder {}
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