Sitelet https://github.com/flutter/flutter/pull/152243/files
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions dev/devicelab/bin/tasks/build_ios_framework_module_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals

section('Check debug build has no Dart AOT');

final String aotSymbols = await dumpSymbolTable(debugAppFrameworkPath);
final String aotSymbols = await _dylibSymbols(debugAppFrameworkPath);

if (aotSymbols.contains('architecture') ||
aotSymbols.contains('_kDartVmSnapshot')) {
Expand All @@ -172,7 +172,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals

await _checkDylib(appFrameworkPath);

final String aotSymbols = await dumpSymbolTable(appFrameworkPath);
final String aotSymbols = await _dylibSymbols(appFrameworkPath);

if (!aotSymbols.contains('_kDartVmSnapshot')) {
throw TaskResult.failure('$mode App.framework missing Dart AOT');
Expand Down Expand Up @@ -562,7 +562,7 @@ Future<void> _testBuildMacOSFramework(Directory projectDir) async {

section('Check debug build has no Dart AOT');

final String aotSymbols = await dumpSymbolTable(debugAppFrameworkPath);
final String aotSymbols = await _dylibSymbols(debugAppFrameworkPath);

if (aotSymbols.contains('architecture') ||
aotSymbols.contains('_kDartVmSnapshot')) {
Expand All @@ -583,7 +583,7 @@ Future<void> _testBuildMacOSFramework(Directory projectDir) async {

await _checkDylib(appFrameworkPath);

final String aotSymbols = await dumpSymbolTable(appFrameworkPath);
final String aotSymbols = await _dylibSymbols(appFrameworkPath);

if (!aotSymbols.contains('_kDartVmSnapshot')) {
throw TaskResult.failure('$mode App.framework missing Dart AOT');
Expand Down Expand Up @@ -939,6 +939,15 @@ Future<void> _checkStatic(String pathToLibrary) async {
}
}

Future<String> _dylibSymbols(String pathToDylib) {
return eval('nm', <String>[
'-g',
pathToDylib,
'-arch',
'arm64',
]);
}

Future<bool> _linksOnFlutter(String pathToBinary) async {
final String loadCommands = await eval('otool', <String>[
'-l',
Expand Down
8 changes: 7 additions & 1 deletion dev/devicelab/bin/tasks/module_test_ios.dart
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,13 @@ Future<bool> _isAppAotBuild(Directory app) async {
'App',
);

final String symbolTable = await dumpSymbolTable(binary);
final String symbolTable = await eval(
'nm',
<String> [
'-gU',
binary,
],
);

return symbolTable.contains('kDartIsolateSnapshotInstructions');
}
Expand Down
53 changes: 22 additions & 31 deletions dev/devicelab/bin/tasks/plugin_dependencies_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'dart:convert';
import 'dart:io';

import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/framework/ios.dart';
import 'package:flutter_devicelab/framework/task_result.dart';
import 'package:flutter_devicelab/framework/utils.dart';
import 'package:path/path.dart' as path;
Expand Down Expand Up @@ -210,7 +209,6 @@ public class DummyPluginAClass {
final String flutterPluginsDependenciesFileContent = flutterPluginsDependenciesFile.readAsStringSync();

final Map<String, dynamic> jsonContent = json.decode(flutterPluginsDependenciesFileContent) as Map<String, dynamic>;
final bool swiftPackageManagerEnabled = jsonContent['swift_package_manager_enabled'] as bool? ?? false;

// Verify the dependencyGraph object is valid. The rest of the contents of this file are not relevant to the
// dependency graph and are tested by unit tests.
Expand Down Expand Up @@ -304,35 +302,28 @@ public class DummyPluginAClass {
return TaskResult.failure('Failed to build plugin A example iOS app');
}

if (swiftPackageManagerEnabled) {
// Check plugins are built statically if using SwiftPM.
final String executable = path.join(appBundle.path, 'Runner');
final String symbols = await dumpSymbolTable(executable);

final bool foundA = symbols.contains('plugin_a');
final bool foundB = symbols.contains('plugin_b');
final bool foundC = symbols.contains('plugin_c');
final bool foundD = symbols.contains('plugin_d');

if (!foundA || !foundB || !foundC) {
return TaskResult.failure(
'Failed to find plugins_a, plugin_b, or plugin_c symbols in the app'
);
}

if (foundD) {
return TaskResult.failure(
'Found Android plugin_d symbols in iOS app'
);
}
} else {
// Check plugins are built dynamically if using CocoaPods.
checkDirectoryExists(path.join(appBundle.path, 'Frameworks', 'plugin_a.framework'));
checkDirectoryExists(path.join(appBundle.path, 'Frameworks', 'plugin_b.framework'));
checkDirectoryExists(path.join(appBundle.path, 'Frameworks', 'plugin_c.framework'));

checkDirectoryNotExists(path.join(appBundle.path, 'Frameworks', 'plugin_d.framework'));
}
checkDirectoryExists(path.join(
appBundle.path,
'Frameworks',
'plugin_a.framework',
));
checkDirectoryExists(path.join(
appBundle.path,
'Frameworks',
'plugin_b.framework',
));
checkDirectoryExists(path.join(
appBundle.path,
'Frameworks',
'plugin_c.framework',
));

// Plugin D is Android only and should not be embedded.
checkDirectoryNotExists(path.join(
appBundle.path,
'Frameworks',
'plugin_d.framework',
));
}

return TaskResult.success(null);
Expand Down
14 changes: 0 additions & 14 deletions dev/devicelab/lib/framework/ios.dart
Original file line number Diff line number Diff line change
Expand Up @@ -308,17 +308,3 @@ File? _createDisabledSandboxEntitlementFile(

return disabledSandboxEntitlementFile;
}

/// Returns global (external) symbol table entries, delimited by new lines.
Future<String> dumpSymbolTable(String filePath) {
return eval(
'nm',
<String>[
'--extern-only',
'--just-symbol-name',
filePath,
'-arch',
'arm64',
],
);
}
105 changes: 34 additions & 71 deletions dev/devicelab/lib/tasks/plugin_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ class PluginTest {
final _FlutterProject app = await _FlutterProject.create(tempDir, options, buildTarget,
name: 'plugintestapp', template: 'app', environment: appCreateEnvironment);
try {
if (cocoapodsTransitiveFlutterDependency) {
section('Disable Swift Package Manager');
await app.disableSwiftPackageManager();
}

section('Add plugins');
await app.addPlugin('plugintest',
pluginPath: path.join('..', 'plugintest'));
Expand Down Expand Up @@ -152,20 +147,6 @@ class _FlutterProject {
return _FlutterProject(Directory(path.join(rootPath)), 'example');
}

Future<void> disableSwiftPackageManager() async {
final File pubspec = pubspecFile;
String content = await pubspec.readAsString();
content = content.replaceFirst(
'# The following section is specific to Flutter packages.\n'
'flutter:\n',
'# The following section is specific to Flutter packages.\n'
'flutter:\n'
'\n'
' disable-swift-package-manager: true\n'
);
await pubspec.writeAsString(content, flush: true);
}

Future<void> addPlugin(String plugin, {String? pluginPath}) async {
final File pubspec = pubspecFile;
String content = await pubspec.readAsString();
Expand Down Expand Up @@ -263,14 +244,9 @@ class $dartPluginClass {
await podspec.writeAsString(podspecContent, flush: true);

// Make PlugintestPlugin.swift compile on iOS and macOS with target conditionals.
// If SwiftPM is disabled, the file will be in `darwin/Classes/`.
// Otherwise, the file will be in `darwin/<plugin>/Sources/<plugin>/`.
final String pluginClass = '${name[0].toUpperCase()}${name.substring(1)}Plugin';
print('pluginClass: $pluginClass');
File pluginRegister = File(path.join(darwinDir.path, 'Classes', '$pluginClass.swift'));
if (!pluginRegister.existsSync()) {
pluginRegister = File(path.join(darwinDir.path, name, 'Sources', name, '$pluginClass.swift'));
}
final File pluginRegister = File(path.join(darwinDir.path, 'Classes', '$pluginClass.swift'));
final String pluginRegisterContent = '''
#if os(macOS)
import FlutterMacOS
Expand Down Expand Up @@ -518,55 +494,42 @@ s.dependency 'AppAuth', '1.6.0'
}

if (validateNativeBuildProject) {
final File generatedSwiftManifest = File(path.join(
rootPath,
target,
'Flutter',
'ephemeral',
'Packages',
'FlutterGeneratedPluginSwiftPackage',
'Package.swift'
));
final bool swiftPackageManagerEnabled = generatedSwiftManifest.existsSync();

if (!swiftPackageManagerEnabled) {
final File podsProject = File(path.join(rootPath, target, 'Pods', 'Pods.xcodeproj', 'project.pbxproj'));
if (!podsProject.existsSync()) {
throw TaskResult.failure('Xcode Pods project file missing at ${podsProject.path}');
}
final File podsProject = File(path.join(rootPath, target, 'Pods', 'Pods.xcodeproj', 'project.pbxproj'));
if (!podsProject.existsSync()) {
throw TaskResult.failure('Xcode Pods project file missing at ${podsProject.path}');
}

final String podsProjectContent = podsProject.readAsStringSync();
if (target == 'ios') {
// Plugins with versions lower than the app version should not have IPHONEOS_DEPLOYMENT_TARGET set.
// The plugintest plugin target should not have IPHONEOS_DEPLOYMENT_TARGET set since it has been lowered
// in _reduceDarwinPluginMinimumVersion to 10, which is below the target version of 11.
if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 10')) {
throw TaskResult.failure('Plugin build setting IPHONEOS_DEPLOYMENT_TARGET not removed');
}
// Transitive dependency AppAuth targeting too-low 8.0 was not fixed.
if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 8')) {
throw TaskResult.failure('Transitive dependency build setting IPHONEOS_DEPLOYMENT_TARGET=8 not removed');
}
if (!podsProjectContent.contains(r'"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited) i386";')) {
throw TaskResult.failure(r'EXCLUDED_ARCHS is not "$(inherited) i386"');
}
} else if (target == 'macos') {
// Same for macOS deployment target, but 10.8.
// The plugintest target should not have MACOSX_DEPLOYMENT_TARGET set.
if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.8')) {
throw TaskResult.failure('Plugin build setting MACOSX_DEPLOYMENT_TARGET not removed');
}
// Transitive dependency AppAuth targeting too-low 10.9 was not fixed.
if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.9')) {
throw TaskResult.failure('Transitive dependency build setting MACOSX_DEPLOYMENT_TARGET=10.9 not removed');
}
final String podsProjectContent = podsProject.readAsStringSync();
if (target == 'ios') {
// Plugins with versions lower than the app version should not have IPHONEOS_DEPLOYMENT_TARGET set.
// The plugintest plugin target should not have IPHONEOS_DEPLOYMENT_TARGET set since it has been lowered
// in _reduceDarwinPluginMinimumVersion to 10, which is below the target version of 11.
if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 10')) {
throw TaskResult.failure('Plugin build setting IPHONEOS_DEPLOYMENT_TARGET not removed');
}
// Transitive dependency AppAuth targeting too-low 8.0 was not fixed.
if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 8')) {
throw TaskResult.failure('Transitive dependency build setting IPHONEOS_DEPLOYMENT_TARGET=8 not removed');
}
if (!podsProjectContent.contains(r'"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited) i386";')) {
throw TaskResult.failure(r'EXCLUDED_ARCHS is not "$(inherited) i386"');
}
} else if (target == 'macos') {
// Same for macOS deployment target, but 10.8.
// The plugintest target should not have MACOSX_DEPLOYMENT_TARGET set.
if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.8')) {
throw TaskResult.failure('Plugin build setting MACOSX_DEPLOYMENT_TARGET not removed');
}
// Transitive dependency AppAuth targeting too-low 10.9 was not fixed.
if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.9')) {
throw TaskResult.failure('Transitive dependency build setting MACOSX_DEPLOYMENT_TARGET=10.9 not removed');
}
}

if (localEngine != null) {
final RegExp localEngineSearchPath = RegExp('FRAMEWORK_SEARCH_PATHS\\s*=[^;]*${localEngine.path}');
if (!localEngineSearchPath.hasMatch(podsProjectContent)) {
throw TaskResult.failure('FRAMEWORK_SEARCH_PATHS does not contain the --local-engine path');
}
if (localEngine != null) {
final RegExp localEngineSearchPath = RegExp('FRAMEWORK_SEARCH_PATHS\\s*=[^;]*${localEngine.path}');
if (!localEngineSearchPath.hasMatch(podsProjectContent)) {
throw TaskResult.failure('FRAMEWORK_SEARCH_PATHS does not contain the --local-engine path');
}
}
}
Expand Down
1 change: 0 additions & 1 deletion packages/flutter_tools/lib/src/features.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ const Feature swiftPackageManager = Feature(
environmentOverride: 'SWIFT_PACKAGE_MANAGER',
master: FeatureChannelSetting(
available: true,
enabledByDefault: true,
),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ void main() {
),
});

testUsingContext('kotlin/swift plugin project without Swift Package Manager', () async {
testUsingContext('kotlin/swift plugin project', () async {
return _createProject(
projectDir,
<String>['--no-pub', '--template=plugin', '-a', 'kotlin', '--ios-language', 'swift', '--platforms', 'ios,android'],
Expand All @@ -718,9 +718,6 @@ void main() {
'ios/Classes/FlutterProjectPlugin.m',
],
);
}, overrides: <Type, Generator>{
// Test flags disable Swift Package Manager.
FeatureFlags: () => TestFeatureFlags(),
});

testUsingContext('swift plugin project with Swift Package Manager', () async {
Expand Down Expand Up @@ -1947,7 +1944,7 @@ void main() {
);
});

testUsingContext('can re-gen plugin ios/ and example/ folders, reusing custom org, without Swift Package Manager', () async {
testUsingContext('can re-gen plugin ios/ and example/ folders, reusing custom org', () async {
await _createProject(
projectDir,
<String>[
Expand All @@ -1972,56 +1969,13 @@ void main() {
unexpectedPaths: <String>[
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
'ios/flutter_project/Sources/flutter_project/include/flutter_project/FlutterProjectPlugin.h',
],
);
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
expect(
await project.example.ios.productBundleIdentifier(BuildInfo.debug),
'com.bar.foo.flutterProjectExample',
);
}, overrides: <Type, Generator>{
// Test flags disable Swift Package Manager.
FeatureFlags: () => TestFeatureFlags(),
});

testUsingContext('can re-gen plugin ios/ and example/ folders, reusing custom org, with Swift Package Manager', () async {
await _createProject(
projectDir,
<String>[
'--no-pub',
'--template=plugin',
'--org', 'com.bar.foo',
'-i', 'objc',
'-a', 'java',
'--platforms', 'ios,android',
],
<String>[],
);
projectDir.childDirectory('example').deleteSync(recursive: true);
projectDir.childDirectory('ios').deleteSync(recursive: true);
await _createProject(
projectDir,
<String>['--no-pub', '--template=plugin', '-i', 'objc', '-a', 'java', '--platforms', 'ios,android'],
<String>[
'example/android/app/src/main/java/com/bar/foo/flutter_project_example/MainActivity.java',
'ios/flutter_project/Sources/flutter_project/include/flutter_project/FlutterProjectPlugin.h',
],
unexpectedPaths: <String>[
'example/android/app/src/main/java/com/example/flutter_project_example/MainActivity.java',
'android/src/main/java/com/example/flutter_project/FlutterProjectPlugin.java',
'ios/Classes/FlutterProjectPlugin.h',
],
);
final FlutterProject project = FlutterProject.fromDirectory(projectDir);
expect(
await project.example.ios.productBundleIdentifier(BuildInfo.debug),
'com.bar.foo.flutterProjectExample',
);
}, overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(
isSwiftPackageManagerEnabled: true,
),
});

testUsingContext('fails to re-gen without specified org when org is ambiguous', () async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void main() {
});

test('${swiftPackageManager.name} availability and default enabled', () {
expect(swiftPackageManager.master.enabledByDefault, true);
expect(swiftPackageManager.master.enabledByDefault, false);
expect(swiftPackageManager.master.available, true);
expect(swiftPackageManager.beta.enabledByDefault, false);
expect(swiftPackageManager.beta.available, false);
Expand Down
Loading