[flutter_tools] wire up complete support for Dart obfuscation (#50509)
This commit is contained in:
parent
baa4b78333
commit
08d079f6c2
62
dev/devicelab/bin/tasks/android_obfuscate_test.dart
Normal file
62
dev/devicelab/bin/tasks/android_obfuscate_test.dart
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2014 The Flutter 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 'package:flutter_devicelab/framework/apk_utils.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/framework.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/utils.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
await task(() async {
|
||||||
|
try {
|
||||||
|
bool foundProjectName = false;
|
||||||
|
await runProjectTest((FlutterProject flutterProject) async {
|
||||||
|
section('APK content for task assembleRelease with --obfuscate');
|
||||||
|
await inDirectory(flutterProject.rootPath, () async {
|
||||||
|
await flutter('build', options: <String>[
|
||||||
|
'apk',
|
||||||
|
'--target-platform=android-arm',
|
||||||
|
'--obfuscate',
|
||||||
|
'--split-debug-info=foo/',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
final String outputDirectory = path.join(
|
||||||
|
flutterProject.rootPath,
|
||||||
|
'build/app/outputs/apk/release/app-release.apk',
|
||||||
|
);
|
||||||
|
final Iterable<String> apkFiles = await getFilesInApk(outputDirectory);
|
||||||
|
|
||||||
|
checkCollectionContains<String>(<String>[
|
||||||
|
...flutterAssets,
|
||||||
|
...baseApkFiles,
|
||||||
|
'lib/armeabi-v7a/libapp.so',
|
||||||
|
], apkFiles);
|
||||||
|
|
||||||
|
// Verify that an identifier from the Dart project code is not present
|
||||||
|
// in the compiled binary.
|
||||||
|
await inDirectory(flutterProject.rootPath, () async {
|
||||||
|
await exec('unzip', <String>[outputDirectory]);
|
||||||
|
final String response = await eval(
|
||||||
|
'grep',
|
||||||
|
<String>[flutterProject.name, 'lib/armeabi-v7a/libapp.so'],
|
||||||
|
canFail: true,
|
||||||
|
);
|
||||||
|
if (response.trim().contains('matches')) {
|
||||||
|
foundProjectName = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (foundProjectName) {
|
||||||
|
return TaskResult.failure('Found project name in obfuscated dart library');
|
||||||
|
}
|
||||||
|
return TaskResult.success(null);
|
||||||
|
} on TaskResult catch (taskResult) {
|
||||||
|
return taskResult;
|
||||||
|
} catch (e) {
|
||||||
|
return TaskResult.failure(e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
58
dev/devicelab/bin/tasks/ios_obfuscate_test.dart
Normal file
58
dev/devicelab/bin/tasks/ios_obfuscate_test.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2014 The Flutter 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:flutter_devicelab/framework/apk_utils.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/framework.dart';
|
||||||
|
import 'package:flutter_devicelab/framework/utils.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
await task(() async {
|
||||||
|
try {
|
||||||
|
bool foundProjectName = false;
|
||||||
|
await runProjectTest((FlutterProject flutterProject) async {
|
||||||
|
section('iOS Framework content with --obfuscate');
|
||||||
|
await inDirectory(flutterProject.rootPath, () async {
|
||||||
|
await flutter('build', options: <String>[
|
||||||
|
'ios',
|
||||||
|
'--release',
|
||||||
|
'--obfuscate',
|
||||||
|
'--split-debug-info=foo/',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
final String outputFramework = path.join(
|
||||||
|
flutterProject.rootPath,
|
||||||
|
'build/ios/iphoneos/Runner.app/Frameworks/App.framework/App',
|
||||||
|
);
|
||||||
|
if (!File(outputFramework).existsSync()) {
|
||||||
|
fail('Failed to produce expected output at $outputFramework');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that an identifier from the Dart project code is not present
|
||||||
|
// in the compiled binary.
|
||||||
|
await inDirectory(flutterProject.rootPath, () async {
|
||||||
|
final String response = await eval(
|
||||||
|
'grep',
|
||||||
|
<String>[flutterProject.name, outputFramework],
|
||||||
|
canFail: true,
|
||||||
|
);
|
||||||
|
if (response.trim().contains('matches')) {
|
||||||
|
foundProjectName = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (foundProjectName) {
|
||||||
|
return TaskResult.failure('Found project name in obfuscated dart library');
|
||||||
|
}
|
||||||
|
return TaskResult.success(null);
|
||||||
|
} on TaskResult catch (taskResult) {
|
||||||
|
return taskResult;
|
||||||
|
} catch (e) {
|
||||||
|
return TaskResult.failure(e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -319,6 +319,13 @@ tasks:
|
|||||||
stage: devicelab
|
stage: devicelab
|
||||||
required_agent_capabilities: ["mac/android"]
|
required_agent_capabilities: ["mac/android"]
|
||||||
|
|
||||||
|
android_obfuscate_test:
|
||||||
|
description: >
|
||||||
|
Builds an obfuscated APK and verifies a dart identifier cannot be found
|
||||||
|
stage: devicelab
|
||||||
|
flaky: true
|
||||||
|
required_agent_capabilities: ["linux/android"]
|
||||||
|
|
||||||
complex_layout_semantics_perf:
|
complex_layout_semantics_perf:
|
||||||
description: >
|
description: >
|
||||||
Measures duration of building the initial semantics tree.
|
Measures duration of building the initial semantics tree.
|
||||||
@ -390,6 +397,13 @@ tasks:
|
|||||||
|
|
||||||
# iOS on-device tests
|
# iOS on-device tests
|
||||||
|
|
||||||
|
ios_obfuscate_test:
|
||||||
|
description: >
|
||||||
|
Builds an obfuscated APK and verifies a dart identifier cannot be found
|
||||||
|
stage: devicelab
|
||||||
|
flaky: true
|
||||||
|
required_agent_capabilities: ["mac/ios"]
|
||||||
|
|
||||||
tiles_scroll_perf_ios__timeline_summary:
|
tiles_scroll_perf_ios__timeline_summary:
|
||||||
description: >
|
description: >
|
||||||
Measures the runtime performance of the tiles tab in the Complex Layout sample app on iPhone 6.
|
Measures the runtime performance of the tiles tab in the Complex Layout sample app on iPhone 6.
|
||||||
|
@ -67,6 +67,11 @@ if [[ -n "$TREE_SHAKE_ICONS" ]]; then
|
|||||||
icon_tree_shaker_flag="true"
|
icon_tree_shaker_flag="true"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dart_obfuscation_flag="false"
|
||||||
|
if [[ -n "$DART_OBFUSCATION" ]]; then
|
||||||
|
dart_obfuscation_flag="true"
|
||||||
|
fi
|
||||||
|
|
||||||
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
|
RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
|
||||||
${verbose_flag} \
|
${verbose_flag} \
|
||||||
${flutter_engine_flag} \
|
${flutter_engine_flag} \
|
||||||
@ -76,6 +81,7 @@ RunCommand "${FLUTTER_ROOT}/bin/flutter" --suppress-analytics \
|
|||||||
-dTargetFile="${target_path}" \
|
-dTargetFile="${target_path}" \
|
||||||
-dBuildMode="${build_mode}" \
|
-dBuildMode="${build_mode}" \
|
||||||
-dTreeShakeIcons="${icon_tree_shaker_flag}" \
|
-dTreeShakeIcons="${icon_tree_shaker_flag}" \
|
||||||
|
-dDartObfuscation="${dart_obfuscation_flag}" \
|
||||||
-dSplitDebugInfo="${SPLIT_DEBUG_INFO}" \
|
-dSplitDebugInfo="${SPLIT_DEBUG_INFO}" \
|
||||||
--build-inputs="${build_inputs_path}" \
|
--build-inputs="${build_inputs_path}" \
|
||||||
--build-outputs="${build_outputs_path}" \
|
--build-outputs="${build_outputs_path}" \
|
||||||
|
@ -166,6 +166,11 @@ BuildApp() {
|
|||||||
icon_tree_shaker_flag="true"
|
icon_tree_shaker_flag="true"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dart_obfuscation_flag="false"
|
||||||
|
if [[ -n "$DART_OBFUSCATION" ]]; then
|
||||||
|
dart_obfuscation_flag="true"
|
||||||
|
fi
|
||||||
|
|
||||||
RunCommand "${FLUTTER_ROOT}/bin/flutter" \
|
RunCommand "${FLUTTER_ROOT}/bin/flutter" \
|
||||||
${verbose_flag} \
|
${verbose_flag} \
|
||||||
${flutter_engine_flag} \
|
${flutter_engine_flag} \
|
||||||
@ -179,6 +184,7 @@ BuildApp() {
|
|||||||
-dSplitDebugInfo="${SPLIT_DEBUG_INFO}" \
|
-dSplitDebugInfo="${SPLIT_DEBUG_INFO}" \
|
||||||
-dTreeShakeIcons="${icon_tree_shaker_flag}" \
|
-dTreeShakeIcons="${icon_tree_shaker_flag}" \
|
||||||
-dTrackWidgetCreation="${track_widget_creation_flag}" \
|
-dTrackWidgetCreation="${track_widget_creation_flag}" \
|
||||||
|
-dDartObfuscation="${dart_obfuscation_flag}" \
|
||||||
-dEnableBitcode="${bitcode_flag}" \
|
-dEnableBitcode="${bitcode_flag}" \
|
||||||
"${build_mode}_ios_bundle_flutter_assets"
|
"${build_mode}_ios_bundle_flutter_assets"
|
||||||
|
|
||||||
|
@ -607,6 +607,10 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
if (project.hasProperty('split-debug-info')) {
|
if (project.hasProperty('split-debug-info')) {
|
||||||
splitDebugInfoValue = project.property('split-debug-info')
|
splitDebugInfoValue = project.property('split-debug-info')
|
||||||
}
|
}
|
||||||
|
Boolean dartObfuscationValue = false
|
||||||
|
if (project.hasProperty('dart-obfuscation')) {
|
||||||
|
dartObfuscationValue = project.property('dart-obfuscation').toBoolean();
|
||||||
|
}
|
||||||
Boolean treeShakeIconsOptionsValue = false
|
Boolean treeShakeIconsOptionsValue = false
|
||||||
if (project.hasProperty('tree-shake-icons')) {
|
if (project.hasProperty('tree-shake-icons')) {
|
||||||
treeShakeIconsOptionsValue = project.property('tree-shake-icons').toBoolean()
|
treeShakeIconsOptionsValue = project.property('tree-shake-icons').toBoolean()
|
||||||
@ -647,6 +651,7 @@ class FlutterPlugin implements Plugin<Project> {
|
|||||||
extraGenSnapshotOptions extraGenSnapshotOptionsValue
|
extraGenSnapshotOptions extraGenSnapshotOptionsValue
|
||||||
splitDebugInfo splitDebugInfoValue
|
splitDebugInfo splitDebugInfoValue
|
||||||
treeShakeIcons treeShakeIconsOptionsValue
|
treeShakeIcons treeShakeIconsOptionsValue
|
||||||
|
dartObfuscation dartObfuscationValue
|
||||||
doLast {
|
doLast {
|
||||||
project.exec {
|
project.exec {
|
||||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||||
@ -792,6 +797,8 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||||||
String splitDebugInfo
|
String splitDebugInfo
|
||||||
@Optional @Input
|
@Optional @Input
|
||||||
Boolean treeShakeIcons
|
Boolean treeShakeIcons
|
||||||
|
@Optional @Input
|
||||||
|
Boolean dartObfuscation
|
||||||
|
|
||||||
@OutputFiles
|
@OutputFiles
|
||||||
FileCollection getDependenciesFiles() {
|
FileCollection getDependenciesFiles() {
|
||||||
@ -854,6 +861,9 @@ abstract class BaseFlutterTask extends DefaultTask {
|
|||||||
if (treeShakeIcons == true) {
|
if (treeShakeIcons == true) {
|
||||||
args "-dTreeShakeIcons=true"
|
args "-dTreeShakeIcons=true"
|
||||||
}
|
}
|
||||||
|
if (dartObfuscation == true) {
|
||||||
|
args "-dDartObfuscation=true"
|
||||||
|
}
|
||||||
if (extraGenSnapshotOptions != null) {
|
if (extraGenSnapshotOptions != null) {
|
||||||
args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}"
|
args "--ExtraGenSnapshotOptions=${extraGenSnapshotOptions}"
|
||||||
}
|
}
|
||||||
|
@ -344,6 +344,9 @@ Future<void> buildGradleApp({
|
|||||||
if (androidBuildInfo.buildInfo.treeShakeIcons) {
|
if (androidBuildInfo.buildInfo.treeShakeIcons) {
|
||||||
command.add('-Ptree-shake-icons=true');
|
command.add('-Ptree-shake-icons=true');
|
||||||
}
|
}
|
||||||
|
if (androidBuildInfo.buildInfo.dartObfuscation) {
|
||||||
|
command.add('-Pdart-obfuscation=true');
|
||||||
|
}
|
||||||
command.add(assembleTask);
|
command.add(assembleTask);
|
||||||
|
|
||||||
GradleHandledError detectedGradleError;
|
GradleHandledError detectedGradleError;
|
||||||
|
@ -93,6 +93,7 @@ class AotBuilder {
|
|||||||
bitcode: bitcode,
|
bitcode: bitcode,
|
||||||
quiet: quiet,
|
quiet: quiet,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
).then<int>((int buildExitCode) {
|
).then<int>((int buildExitCode) {
|
||||||
return buildExitCode;
|
return buildExitCode;
|
||||||
});
|
});
|
||||||
@ -130,6 +131,7 @@ class AotBuilder {
|
|||||||
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
if (snapshotExitCode != 0) {
|
if (snapshotExitCode != 0) {
|
||||||
status?.cancel();
|
status?.cancel();
|
||||||
|
@ -42,6 +42,16 @@ class GenSnapshot {
|
|||||||
Artifact.genSnapshot, platform: snapshotType.platform, mode: snapshotType.mode);
|
Artifact.genSnapshot, platform: snapshotType.platform, mode: snapshotType.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ignored warning messages from gen_snapshot.
|
||||||
|
static const Set<String> kIgnoredWarnings = <String>{
|
||||||
|
// --strip on elf snapshot.
|
||||||
|
'Warning: Generating ELF library without DWARF debugging information.',
|
||||||
|
// --strip on ios-assembly snapshot.
|
||||||
|
'Warning: Generating assembly code without DWARF debugging information.',
|
||||||
|
// A fun two-part message with spaces for obfuscation.
|
||||||
|
'Warning: This VM has been configured to obfuscate symbol information which violates the Dart standard.',
|
||||||
|
' See dartbug.com/30524 for more information.',
|
||||||
|
};
|
||||||
Future<int> run({
|
Future<int> run({
|
||||||
@required SnapshotType snapshotType,
|
@required SnapshotType snapshotType,
|
||||||
DarwinArch darwinArch,
|
DarwinArch darwinArch,
|
||||||
@ -59,18 +69,9 @@ class GenSnapshot {
|
|||||||
snapshotterPath += '_' + getNameForDarwinArch(darwinArch);
|
snapshotterPath += '_' + getNameForDarwinArch(darwinArch);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringConverter outputFilter;
|
|
||||||
if (additionalArgs.contains('--strip')) {
|
|
||||||
// Filter out gen_snapshot's warning message about stripping debug symbols
|
|
||||||
// from ELF library snapshots.
|
|
||||||
const String kStripWarning = 'Warning: Generating ELF library without DWARF debugging information.';
|
|
||||||
const String kAssemblyStripWarning = 'Warning: Generating assembly code without DWARF debugging information.';
|
|
||||||
outputFilter = (String line) => line != kStripWarning && line != kAssemblyStripWarning ? line : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return processUtils.stream(
|
return processUtils.stream(
|
||||||
<String>[snapshotterPath, ...args],
|
<String>[snapshotterPath, ...args],
|
||||||
mapFunction: outputFilter,
|
mapFunction: (String line) => kIgnoredWarnings.contains(line) ? null : line,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,6 +95,7 @@ class AOTSnapshotter {
|
|||||||
List<String> extraGenSnapshotOptions = const <String>[],
|
List<String> extraGenSnapshotOptions = const <String>[],
|
||||||
@required bool bitcode,
|
@required bool bitcode,
|
||||||
@required String splitDebugInfo,
|
@required String splitDebugInfo,
|
||||||
|
@required bool dartObfuscation,
|
||||||
bool quiet = false,
|
bool quiet = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (bitcode && platform != TargetPlatform.ios) {
|
if (bitcode && platform != TargetPlatform.ios) {
|
||||||
@ -147,7 +149,8 @@ class AOTSnapshotter {
|
|||||||
// multiple debug files.
|
// multiple debug files.
|
||||||
final String archName = getNameForTargetPlatform(platform, darwinArch: darwinArch);
|
final String archName = getNameForTargetPlatform(platform, darwinArch: darwinArch);
|
||||||
final String debugFilename = 'app.$archName.symbols';
|
final String debugFilename = 'app.$archName.symbols';
|
||||||
if (splitDebugInfo?.isNotEmpty ?? false) {
|
final bool shouldSplitDebugInfo = splitDebugInfo?.isNotEmpty ?? false;
|
||||||
|
if (shouldSplitDebugInfo) {
|
||||||
globals.fs.directory(splitDebugInfo)
|
globals.fs.directory(splitDebugInfo)
|
||||||
.createSync(recursive: true);
|
.createSync(recursive: true);
|
||||||
}
|
}
|
||||||
@ -157,10 +160,12 @@ class AOTSnapshotter {
|
|||||||
// Faster async/await
|
// Faster async/await
|
||||||
'--no-causal-async-stacks',
|
'--no-causal-async-stacks',
|
||||||
'--lazy-async-stacks',
|
'--lazy-async-stacks',
|
||||||
if (splitDebugInfo?.isNotEmpty ?? false) ...<String>[
|
if (shouldSplitDebugInfo) ...<String>[
|
||||||
'--dwarf-stack-traces',
|
'--dwarf-stack-traces',
|
||||||
'--save-debugging-info=${globals.fs.path.join(splitDebugInfo, debugFilename)}'
|
'--save-debugging-info=${globals.fs.path.join(splitDebugInfo, debugFilename)}'
|
||||||
]
|
],
|
||||||
|
if (dartObfuscation)
|
||||||
|
'--obfuscate',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
genSnapshotArgs.add(mainPath);
|
genSnapshotArgs.add(mainPath);
|
||||||
|
@ -22,6 +22,7 @@ class BuildInfo {
|
|||||||
this.buildNumber,
|
this.buildNumber,
|
||||||
this.buildName,
|
this.buildName,
|
||||||
this.splitDebugInfoPath,
|
this.splitDebugInfoPath,
|
||||||
|
this.dartObfuscation = false,
|
||||||
@required this.treeShakeIcons,
|
@required this.treeShakeIcons,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -68,6 +69,9 @@ class BuildInfo {
|
|||||||
/// executable.
|
/// executable.
|
||||||
final String splitDebugInfoPath;
|
final String splitDebugInfoPath;
|
||||||
|
|
||||||
|
/// Whether to apply dart source code obfuscation.
|
||||||
|
final bool dartObfuscation;
|
||||||
|
|
||||||
static const BuildInfo debug = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
|
static const BuildInfo debug = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
|
||||||
static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
|
static const BuildInfo profile = BuildInfo(BuildMode.profile, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
|
||||||
static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
|
static const BuildInfo jitRelease = BuildInfo(BuildMode.jitRelease, null, treeShakeIcons: kIconTreeShakerEnabledDefault);
|
||||||
|
@ -222,6 +222,7 @@ class AndroidAot extends AotElfBase {
|
|||||||
final List<String> extraGenSnapshotOptions = environment.defines[kExtraGenSnapshotOptions]?.split(',')
|
final List<String> extraGenSnapshotOptions = environment.defines[kExtraGenSnapshotOptions]?.split(',')
|
||||||
?? const <String>[];
|
?? const <String>[];
|
||||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||||
|
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||||
final int snapshotExitCode = await snapshotter.build(
|
final int snapshotExitCode = await snapshotter.build(
|
||||||
platform: targetPlatform,
|
platform: targetPlatform,
|
||||||
buildMode: buildMode,
|
buildMode: buildMode,
|
||||||
@ -231,6 +232,7 @@ class AndroidAot extends AotElfBase {
|
|||||||
bitcode: false,
|
bitcode: false,
|
||||||
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
||||||
splitDebugInfo: splitDebugInfo,
|
splitDebugInfo: splitDebugInfo,
|
||||||
|
dartObfuscation: dartObfuscation,
|
||||||
);
|
);
|
||||||
if (snapshotExitCode != 0) {
|
if (snapshotExitCode != 0) {
|
||||||
throw Exception('AOT snapshotter exited with code $snapshotExitCode');
|
throw Exception('AOT snapshotter exited with code $snapshotExitCode');
|
||||||
|
@ -66,6 +66,9 @@ const String kDartDefines = 'DartDefines';
|
|||||||
/// The other supported value is armv7, the 32-bit iOS architecture.
|
/// The other supported value is armv7, the 32-bit iOS architecture.
|
||||||
const String kIosArchs = 'IosArchs';
|
const String kIosArchs = 'IosArchs';
|
||||||
|
|
||||||
|
/// Whether to enable Dart obfuscation and where to save the symbol map.
|
||||||
|
const String kDartObfuscation = 'DartObfuscation';
|
||||||
|
|
||||||
/// Copies the pre-built flutter bundle.
|
/// Copies the pre-built flutter bundle.
|
||||||
// This is a one-off rule for implementing build bundle in terms of assemble.
|
// This is a one-off rule for implementing build bundle in terms of assemble.
|
||||||
class CopyFlutterBundle extends Target {
|
class CopyFlutterBundle extends Target {
|
||||||
@ -270,7 +273,8 @@ abstract class AotElfBase extends Target {
|
|||||||
?? const <String>[];
|
?? const <String>[];
|
||||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||||
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
||||||
final String saveDebuggingInformation = environment.defines[kSplitDebugInfo];
|
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
||||||
|
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||||
final int snapshotExitCode = await snapshotter.build(
|
final int snapshotExitCode = await snapshotter.build(
|
||||||
platform: targetPlatform,
|
platform: targetPlatform,
|
||||||
buildMode: buildMode,
|
buildMode: buildMode,
|
||||||
@ -279,7 +283,8 @@ abstract class AotElfBase extends Target {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
extraGenSnapshotOptions: extraGenSnapshotOptions,
|
||||||
splitDebugInfo: saveDebuggingInformation
|
splitDebugInfo: splitDebugInfo,
|
||||||
|
dartObfuscation: dartObfuscation,
|
||||||
);
|
);
|
||||||
if (snapshotExitCode != 0) {
|
if (snapshotExitCode != 0) {
|
||||||
throw Exception('AOT snapshotter exited with code $snapshotExitCode');
|
throw Exception('AOT snapshotter exited with code $snapshotExitCode');
|
||||||
|
@ -40,6 +40,7 @@ abstract class AotAssemblyBase extends Target {
|
|||||||
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
final BuildMode buildMode = getBuildModeForName(environment.defines[kBuildMode]);
|
||||||
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
final TargetPlatform targetPlatform = getTargetPlatformForName(environment.defines[kTargetPlatform]);
|
||||||
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
||||||
|
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||||
final List<DarwinArch> iosArchs = environment.defines[kIosArchs]
|
final List<DarwinArch> iosArchs = environment.defines[kIosArchs]
|
||||||
?.split(' ')
|
?.split(' ')
|
||||||
?.map(getIOSArchForName)
|
?.map(getIOSArchForName)
|
||||||
@ -63,6 +64,7 @@ abstract class AotAssemblyBase extends Target {
|
|||||||
bitcode: bitcode,
|
bitcode: bitcode,
|
||||||
quiet: true,
|
quiet: true,
|
||||||
splitDebugInfo: splitDebugInfo,
|
splitDebugInfo: splitDebugInfo,
|
||||||
|
dartObfuscation: dartObfuscation,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
final List<int> results = await Future.wait(pending);
|
final List<int> results = await Future.wait(pending);
|
||||||
|
@ -201,6 +201,7 @@ class CompileMacOSFramework extends Target {
|
|||||||
throw Exception('precompiled macOS framework only supported in release/profile builds.');
|
throw Exception('precompiled macOS framework only supported in release/profile builds.');
|
||||||
}
|
}
|
||||||
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
final String splitDebugInfo = environment.defines[kSplitDebugInfo];
|
||||||
|
final bool dartObfuscation = environment.defines[kDartObfuscation] == 'true';
|
||||||
final int result = await AOTSnapshotter(reportTimings: false).build(
|
final int result = await AOTSnapshotter(reportTimings: false).build(
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
buildMode: buildMode,
|
buildMode: buildMode,
|
||||||
@ -210,6 +211,7 @@ class CompileMacOSFramework extends Target {
|
|||||||
darwinArch: DarwinArch.x86_64,
|
darwinArch: DarwinArch.x86_64,
|
||||||
packagesPath: environment.projectDir.childFile('.packages').path,
|
packagesPath: environment.projectDir.childFile('.packages').path,
|
||||||
splitDebugInfo: splitDebugInfo,
|
splitDebugInfo: splitDebugInfo,
|
||||||
|
dartObfuscation: dartObfuscation,
|
||||||
);
|
);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
throw Exception('gen shapshot failed.');
|
throw Exception('gen shapshot failed.');
|
||||||
|
@ -27,6 +27,7 @@ class BuildApkCommand extends BuildSubCommand {
|
|||||||
usesBuildNameOption();
|
usesBuildNameOption();
|
||||||
addShrinkingFlag();
|
addShrinkingFlag();
|
||||||
addSplitDebugInfoOption();
|
addSplitDebugInfoOption();
|
||||||
|
addDartObfuscationOption();
|
||||||
argParser
|
argParser
|
||||||
..addFlag('split-per-abi',
|
..addFlag('split-per-abi',
|
||||||
negatable: false,
|
negatable: false,
|
||||||
|
@ -24,6 +24,8 @@ class BuildAppBundleCommand extends BuildSubCommand {
|
|||||||
usesBuildNumberOption();
|
usesBuildNumberOption();
|
||||||
usesBuildNameOption();
|
usesBuildNameOption();
|
||||||
addShrinkingFlag();
|
addShrinkingFlag();
|
||||||
|
addSplitDebugInfoOption();
|
||||||
|
addDartObfuscationOption();
|
||||||
|
|
||||||
argParser
|
argParser
|
||||||
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
|
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
|
||||||
|
@ -26,6 +26,7 @@ class BuildIOSCommand extends BuildSubCommand {
|
|||||||
usesPubOption();
|
usesPubOption();
|
||||||
usesBuildNumberOption();
|
usesBuildNumberOption();
|
||||||
usesBuildNameOption();
|
usesBuildNameOption();
|
||||||
|
addDartObfuscationOption();
|
||||||
argParser
|
argParser
|
||||||
..addFlag('simulator',
|
..addFlag('simulator',
|
||||||
help: 'Build for the iOS simulator instead of the device.',
|
help: 'Build for the iOS simulator instead of the device.',
|
||||||
|
@ -49,6 +49,8 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
|
|||||||
usesFlavorOption();
|
usesFlavorOption();
|
||||||
usesPubOption();
|
usesPubOption();
|
||||||
usesDartDefines();
|
usesDartDefines();
|
||||||
|
addSplitDebugInfoOption();
|
||||||
|
addDartObfuscationOption();
|
||||||
argParser
|
argParser
|
||||||
..addFlag('debug',
|
..addFlag('debug',
|
||||||
negatable: true,
|
negatable: true,
|
||||||
|
@ -21,6 +21,7 @@ class BuildMacosCommand extends BuildSubCommand {
|
|||||||
addSplitDebugInfoOption();
|
addSplitDebugInfoOption();
|
||||||
usesTargetOption();
|
usesTargetOption();
|
||||||
addBuildModeFlags();
|
addBuildModeFlags();
|
||||||
|
addDartObfuscationOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -172,6 +172,11 @@ List<String> _xcodeBuildSettingsLines({
|
|||||||
xcodeBuildSettings.add('SPLIT_DEBUG_INFO=${buildInfo.splitDebugInfoPath}');
|
xcodeBuildSettings.add('SPLIT_DEBUG_INFO=${buildInfo.splitDebugInfoPath}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is an optional path to obfuscate and output a mapping.
|
||||||
|
if (buildInfo.dartObfuscation) {
|
||||||
|
xcodeBuildSettings.add('DART_OBFUSCATION=true');
|
||||||
|
}
|
||||||
|
|
||||||
// The build outputs directory, relative to FLUTTER_APPLICATION_PATH.
|
// The build outputs directory, relative to FLUTTER_APPLICATION_PATH.
|
||||||
xcodeBuildSettings.add('FLUTTER_BUILD_DIR=${buildDirOverride ?? getBuildDirectory()}');
|
xcodeBuildSettings.add('FLUTTER_BUILD_DIR=${buildDirOverride ?? getBuildDirectory()}');
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ class FlutterOptions {
|
|||||||
static const String kFileSystemRoot = 'filesystem-root';
|
static const String kFileSystemRoot = 'filesystem-root';
|
||||||
static const String kFileSystemScheme = 'filesystem-scheme';
|
static const String kFileSystemScheme = 'filesystem-scheme';
|
||||||
static const String kSplitDebugInfoOption = 'split-debug-info';
|
static const String kSplitDebugInfoOption = 'split-debug-info';
|
||||||
|
static const String kDartObfuscationOption = 'obfuscate';
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FlutterCommand extends Command<void> {
|
abstract class FlutterCommand extends Command<void> {
|
||||||
@ -393,6 +394,18 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addDartObfuscationOption() {
|
||||||
|
argParser.addFlag(FlutterOptions.kDartObfuscationOption,
|
||||||
|
help: 'In a release build, this flag removes identifiers and replaces them '
|
||||||
|
'with randomized values for the purposes of source code obfuscation. This '
|
||||||
|
'flag must always be combined with "--split-debug-info" option, the '
|
||||||
|
'mapping between the values and the original identifiers is stored in the '
|
||||||
|
'symbol map created in the specified directory. For an app built with this '
|
||||||
|
'flag, the \'flutter symbolize\' command with the right program '
|
||||||
|
'symbol file is required to obtain a human readable stack trace.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void addTreeShakeIconsFlag() {
|
void addTreeShakeIconsFlag() {
|
||||||
argParser.addFlag('tree-shake-icons',
|
argParser.addFlag('tree-shake-icons',
|
||||||
negatable: true,
|
negatable: true,
|
||||||
@ -483,6 +496,10 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute the [BuildInfo] for the current flutter command.
|
||||||
|
///
|
||||||
|
/// Throws a [ToolExit] if the current set of options is not compatible with
|
||||||
|
/// eachother.
|
||||||
BuildInfo getBuildInfo() {
|
BuildInfo getBuildInfo() {
|
||||||
final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') &&
|
final bool trackWidgetCreation = argParser.options.containsKey('track-widget-creation') &&
|
||||||
boolArg('track-widget-creation');
|
boolArg('track-widget-creation');
|
||||||
@ -507,6 +524,20 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final bool dartObfuscation = argParser.options.containsKey(FlutterOptions.kDartObfuscationOption)
|
||||||
|
&& boolArg(FlutterOptions.kDartObfuscationOption);
|
||||||
|
|
||||||
|
final String splitDebugInfoPath = argParser.options.containsKey(FlutterOptions.kSplitDebugInfoOption)
|
||||||
|
? stringArg(FlutterOptions.kSplitDebugInfoOption)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (dartObfuscation && (splitDebugInfoPath == null || splitDebugInfoPath.isEmpty)) {
|
||||||
|
throwToolExit(
|
||||||
|
'"--${FlutterOptions.kDartObfuscationOption}" can only be used in '
|
||||||
|
'combination with "--${FlutterOptions.kSplitDebugInfoOption}"',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return BuildInfo(getBuildMode(),
|
return BuildInfo(getBuildMode(),
|
||||||
argParser.options.containsKey('flavor')
|
argParser.options.containsKey('flavor')
|
||||||
? stringArg('flavor')
|
? stringArg('flavor')
|
||||||
@ -526,12 +557,11 @@ abstract class FlutterCommand extends Command<void> {
|
|||||||
buildName: argParser.options.containsKey('build-name')
|
buildName: argParser.options.containsKey('build-name')
|
||||||
? stringArg('build-name')
|
? stringArg('build-name')
|
||||||
: null,
|
: null,
|
||||||
splitDebugInfoPath: argParser.options.containsKey(FlutterOptions.kSplitDebugInfoOption)
|
|
||||||
? stringArg(FlutterOptions.kSplitDebugInfoOption)
|
|
||||||
: null,
|
|
||||||
treeShakeIcons: argParser.options.containsKey('tree-shake-icons')
|
treeShakeIcons: argParser.options.containsKey('tree-shake-icons')
|
||||||
? boolArg('tree-shake-icons')
|
? boolArg('tree-shake-icons')
|
||||||
: kIconTreeShakerEnabledDefault,
|
: kIconTreeShakerEnabledDefault,
|
||||||
|
splitDebugInfoPath: splitDebugInfoPath,
|
||||||
|
dartObfuscation: dartObfuscation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,5 +36,8 @@ lib/generated_plugin_registrant.dart
|
|||||||
# Symbolication related
|
# Symbolication related
|
||||||
app.*.symbols
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
|
||||||
# Exceptions to above rules.
|
# Exceptions to above rules.
|
||||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||||
|
@ -43,3 +43,6 @@ build/
|
|||||||
|
|
||||||
# Symbolication related
|
# Symbolication related
|
||||||
app.*.symbols
|
app.*.symbols
|
||||||
|
|
||||||
|
# Obfuscation related
|
||||||
|
app.*.map.json
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2014 The Flutter 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/common.dart';
|
||||||
|
import 'package:flutter_tools/src/runner/flutter_command.dart';
|
||||||
|
|
||||||
|
import '../../src/common.dart';
|
||||||
|
import '../../src/context.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testUsingContext('obfuscate requires split-debug-info', () {
|
||||||
|
final FakeBuildCommand command = FakeBuildCommand();
|
||||||
|
final CommandRunner<void> commandRunner = createTestCommandRunner(command);
|
||||||
|
|
||||||
|
expect(() => commandRunner.run(<String>[
|
||||||
|
'build',
|
||||||
|
'--obfuscate',
|
||||||
|
]), throwsA(isA<ToolExit>()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeBuildCommand extends FlutterCommand {
|
||||||
|
FakeBuildCommand() {
|
||||||
|
addSplitDebugInfoOption();
|
||||||
|
addDartObfuscationOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get description => throw UnimplementedError();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get name => 'build';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<FlutterCommandResult> runCommand() async {
|
||||||
|
getBuildInfo();
|
||||||
|
return FlutterCommandResult.success();
|
||||||
|
}
|
||||||
|
}
|
@ -267,6 +267,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
), isNot(equals(0)));
|
), isNot(equals(0)));
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
@ -280,6 +281,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
), isNot(0));
|
), isNot(0));
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
@ -293,6 +295,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
), isNot(0));
|
), isNot(0));
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
@ -320,6 +323,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.armv7,
|
darwinArch: DarwinArch.armv7,
|
||||||
bitcode: true,
|
bitcode: true,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -381,6 +385,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.armv7,
|
darwinArch: DarwinArch.armv7,
|
||||||
bitcode: true,
|
bitcode: true,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -441,6 +446,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.armv7,
|
darwinArch: DarwinArch.armv7,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -469,7 +475,7 @@ void main() {
|
|||||||
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
testUsingContext('builds iOS armv7 profile AOT snapshot with dwarf stack traces', () async {
|
testUsingContext('builds iOS armv7 profile AOT snapshot with dwarStackTraces', () async {
|
||||||
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
||||||
|
|
||||||
final String outputPath = globals.fs.path.join('build', 'foo');
|
final String outputPath = globals.fs.path.join('build', 'foo');
|
||||||
@ -494,6 +500,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.armv7,
|
darwinArch: DarwinArch.armv7,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: 'foo',
|
splitDebugInfo: 'foo',
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -524,6 +531,60 @@ void main() {
|
|||||||
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
|
testUsingContext('builds iOS armv7 profile AOT snapshot with obfuscate', () async {
|
||||||
|
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
||||||
|
|
||||||
|
final String outputPath = globals.fs.path.join('build', 'foo');
|
||||||
|
globals.fs.directory(outputPath).createSync(recursive: true);
|
||||||
|
|
||||||
|
final String assembly = globals.fs.path.join(outputPath, 'snapshot_assembly.S');
|
||||||
|
genSnapshot.outputs = <String, String>{
|
||||||
|
assembly: 'blah blah\n.section __DWARF\nblah blah\n',
|
||||||
|
};
|
||||||
|
|
||||||
|
final RunResult successResult = RunResult(ProcessResult(1, 0, '', ''), <String>['command name', 'arguments...']);
|
||||||
|
when(mockXcode.cc(any)).thenAnswer((_) => Future<RunResult>.value(successResult));
|
||||||
|
when(mockXcode.clang(any)).thenAnswer((_) => Future<RunResult>.value(successResult));
|
||||||
|
|
||||||
|
final int genSnapshotExitCode = await snapshotter.build(
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
buildMode: BuildMode.profile,
|
||||||
|
mainPath: 'main.dill',
|
||||||
|
packagesPath: '.packages',
|
||||||
|
outputPath: outputPath,
|
||||||
|
darwinArch: DarwinArch.armv7,
|
||||||
|
bitcode: false,
|
||||||
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(genSnapshotExitCode, 0);
|
||||||
|
expect(genSnapshot.callCount, 1);
|
||||||
|
expect(genSnapshot.snapshotType.platform, TargetPlatform.ios);
|
||||||
|
expect(genSnapshot.snapshotType.mode, BuildMode.profile);
|
||||||
|
expect(genSnapshot.additionalArgs, <String>[
|
||||||
|
'--deterministic',
|
||||||
|
'--snapshot_kind=app-aot-assembly',
|
||||||
|
'--assembly=$assembly',
|
||||||
|
'--strip',
|
||||||
|
'--no-sim-use-hardfp',
|
||||||
|
'--no-use-integer-division',
|
||||||
|
'--no-causal-async-stacks',
|
||||||
|
'--lazy-async-stacks',
|
||||||
|
'--obfuscate',
|
||||||
|
'main.dill',
|
||||||
|
]);
|
||||||
|
verifyNever(mockXcode.cc(argThat(contains('-fembed-bitcode'))));
|
||||||
|
verifyNever(mockXcode.clang(argThat(contains('-fembed-bitcode'))));
|
||||||
|
|
||||||
|
verify(mockXcode.cc(argThat(contains('-isysroot')))).called(1);
|
||||||
|
verify(mockXcode.clang(argThat(contains('-isysroot')))).called(1);
|
||||||
|
|
||||||
|
final File assemblyFile = globals.fs.file(assembly);
|
||||||
|
expect(assemblyFile.existsSync(), true);
|
||||||
|
expect(assemblyFile.readAsStringSync().contains('.section __DWARF'), true);
|
||||||
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
testUsingContext('builds iOS arm64 profile AOT snapshot', () async {
|
testUsingContext('builds iOS arm64 profile AOT snapshot', () async {
|
||||||
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
||||||
|
|
||||||
@ -547,6 +608,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.arm64,
|
darwinArch: DarwinArch.arm64,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -587,6 +649,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.armv7,
|
darwinArch: DarwinArch.armv7,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -629,6 +692,7 @@ void main() {
|
|||||||
darwinArch: DarwinArch.arm64,
|
darwinArch: DarwinArch.arm64,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -660,6 +724,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -694,6 +759,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: 'foo',
|
splitDebugInfo: 'foo',
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -715,6 +781,41 @@ void main() {
|
|||||||
]);
|
]);
|
||||||
}, overrides: contextOverrides);
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
|
testUsingContext('builds shared library for android-arm with obfuscate', () async {
|
||||||
|
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
||||||
|
|
||||||
|
final String outputPath = globals.fs.path.join('build', 'foo');
|
||||||
|
globals.fs.directory(outputPath).createSync(recursive: true);
|
||||||
|
|
||||||
|
final int genSnapshotExitCode = await snapshotter.build(
|
||||||
|
platform: TargetPlatform.android_arm,
|
||||||
|
buildMode: BuildMode.release,
|
||||||
|
mainPath: 'main.dill',
|
||||||
|
packagesPath: '.packages',
|
||||||
|
outputPath: outputPath,
|
||||||
|
bitcode: false,
|
||||||
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(genSnapshotExitCode, 0);
|
||||||
|
expect(genSnapshot.callCount, 1);
|
||||||
|
expect(genSnapshot.snapshotType.platform, TargetPlatform.android_arm);
|
||||||
|
expect(genSnapshot.snapshotType.mode, BuildMode.release);
|
||||||
|
expect(genSnapshot.additionalArgs, <String>[
|
||||||
|
'--deterministic',
|
||||||
|
'--snapshot_kind=app-aot-elf',
|
||||||
|
'--elf=build/foo/app.so',
|
||||||
|
'--strip',
|
||||||
|
'--no-sim-use-hardfp',
|
||||||
|
'--no-use-integer-division',
|
||||||
|
'--no-causal-async-stacks',
|
||||||
|
'--lazy-async-stacks',
|
||||||
|
'--obfuscate',
|
||||||
|
'main.dill',
|
||||||
|
]);
|
||||||
|
}, overrides: contextOverrides);
|
||||||
|
|
||||||
testUsingContext('builds shared library for android-arm without dwarf stack traces due to empty string', () async {
|
testUsingContext('builds shared library for android-arm without dwarf stack traces due to empty string', () async {
|
||||||
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
globals.fs.file('main.dill').writeAsStringSync('binary magic');
|
||||||
|
|
||||||
@ -729,6 +830,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: '',
|
splitDebugInfo: '',
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -762,6 +864,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
@ -801,6 +904,7 @@ void main() {
|
|||||||
outputPath: outputPath,
|
outputPath: outputPath,
|
||||||
bitcode: false,
|
bitcode: false,
|
||||||
splitDebugInfo: null,
|
splitDebugInfo: null,
|
||||||
|
dartObfuscation: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(genSnapshotExitCode, 0);
|
expect(genSnapshotExitCode, 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user