Unverified Commit dffddf00 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Refactor BuildIOSFrameworkCommand with common darwin baseclass (#105194)

parent 8dbc3884
...@@ -177,9 +177,9 @@ def flutter_install_ios_engine_pod(ios_application_path = nil) ...@@ -177,9 +177,9 @@ def flutter_install_ios_engine_pod(ios_application_path = nil)
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Flutter' s.name = 'Flutter'
s.version = '1.0.0' s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.' s.summary = 'A UI toolkit for beautiful and fast apps.'
s.homepage = 'https://flutter.io' s.homepage = 'https://flutter.dev'
s.license = { :type => 'MIT' } s.license = { :type => 'BSD' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '11.0' s.ios.deployment_target = '11.0'
...@@ -215,9 +215,9 @@ def flutter_install_macos_engine_pod(mac_application_path = nil) ...@@ -215,9 +215,9 @@ def flutter_install_macos_engine_pod(mac_application_path = nil)
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'FlutterMacOS' s.name = 'FlutterMacOS'
s.version = '1.0.0' s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.' s.summary = 'A UI toolkit for beautiful and fast apps.'
s.homepage = 'https://flutter.io' s.homepage = 'https://flutter.dev'
s.license = { :type => 'MIT' } s.license = { :type => 'BSD' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.osx.deployment_target = '10.11' s.osx.deployment_target = '10.11'
......
...@@ -3,10 +3,12 @@ ...@@ -3,10 +3,12 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart'; import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../base/process.dart'; import '../base/process.dart';
...@@ -23,18 +25,14 @@ import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommand ...@@ -23,18 +25,14 @@ import '../runner/flutter_command.dart' show DevelopmentArtifact, FlutterCommand
import '../version.dart'; import '../version.dart';
import 'build.dart'; import 'build.dart';
/// Produces a .framework for integration into a host iOS app. The .framework abstract class BuildFrameworkCommand extends BuildSubCommand {
/// contains the Flutter engine and framework code as well as plugins. It can BuildFrameworkCommand({
/// be integrated into plain Xcode projects without using or other package
/// managers.
class BuildIOSFrameworkCommand extends BuildSubCommand {
BuildIOSFrameworkCommand({
// Instantiating FlutterVersion kicks off networking, so delay until it's needed, but allow test injection. // Instantiating FlutterVersion kicks off networking, so delay until it's needed, but allow test injection.
@visibleForTesting FlutterVersion? flutterVersion, @visibleForTesting FlutterVersion? flutterVersion,
required BuildSystem buildSystem, required BuildSystem buildSystem,
required bool verboseHelp, required bool verboseHelp,
Cache? cache, Cache? cache,
Platform? platform Platform? platform,
}) : _injectedFlutterVersion = flutterVersion, }) : _injectedFlutterVersion = flutterVersion,
_buildSystem = buildSystem, _buildSystem = buildSystem,
_injectedCache = cache, _injectedCache = cache,
...@@ -42,7 +40,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -42,7 +40,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
super(verboseHelp: verboseHelp) { super(verboseHelp: verboseHelp) {
addTreeShakeIconsFlag(); addTreeShakeIconsFlag();
usesTargetOption(); usesTargetOption();
usesFlavorOption();
usesPubOption(); usesPubOption();
usesDartDefineOption(); usesDartDefineOption();
addSplitDebugInfoOption(); addSplitDebugInfoOption();
...@@ -67,16 +64,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -67,16 +64,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
help: 'Whether to produce a framework for the release build configuration. ' help: 'Whether to produce a framework for the release build configuration. '
'By default, all build configurations are built.' 'By default, all build configurations are built.'
) )
..addFlag('universal',
help: '(deprecated) Produce universal frameworks that include all valid architectures.',
hide: !verboseHelp,
)
..addFlag('xcframework',
help: 'Produce xcframeworks that include all valid architectures.',
negatable: false,
defaultsTo: true,
hide: !verboseHelp,
)
..addFlag('cocoapods', ..addFlag('cocoapods',
help: 'Produce a Flutter.podspec instead of an engine Flutter.xcframework (recommended if host app uses CocoaPods).', help: 'Produce a Flutter.podspec instead of an engine Flutter.xcframework (recommended if host app uses CocoaPods).',
) )
...@@ -96,35 +83,27 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -96,35 +83,27 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
} }
final BuildSystem? _buildSystem; final BuildSystem? _buildSystem;
@protected
BuildSystem get buildSystem => _buildSystem ?? globals.buildSystem; BuildSystem get buildSystem => _buildSystem ?? globals.buildSystem;
Cache get _cache => _injectedCache ?? globals.cache; @protected
Cache get cache => _injectedCache ?? globals.cache;
final Cache? _injectedCache; final Cache? _injectedCache;
Platform get _platform => _injectedPlatform ?? globals.platform; @protected
Platform get platform => _injectedPlatform ?? globals.platform;
final Platform? _injectedPlatform; final Platform? _injectedPlatform;
// FlutterVersion.instance kicks off git processing which can sometimes fail, so don't try it until needed. // FlutterVersion.instance kicks off git processing which can sometimes fail, so don't try it until needed.
FlutterVersion get _flutterVersion => _injectedFlutterVersion ?? globals.flutterVersion; @protected
FlutterVersion get flutterVersion => _injectedFlutterVersion ?? globals.flutterVersion;
final FlutterVersion? _injectedFlutterVersion; final FlutterVersion? _injectedFlutterVersion;
@override @override
bool get reportNullSafety => false; bool get reportNullSafety => false;
@override @protected
final String name = 'ios-framework'; late final FlutterProject project = FlutterProject.current();
@override
final String description = 'Produces .xcframeworks for a Flutter project '
'and its plugins for integration into existing, plain Xcode projects.\n'
'This can only be run on macOS hosts.';
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.iOS,
};
late final FlutterProject _project = FlutterProject.current();
Future<List<BuildInfo>> getBuildInfos() async { Future<List<BuildInfo>> getBuildInfos() async {
final List<BuildInfo> buildInfos = <BuildInfo>[]; final List<BuildInfo> buildInfos = <BuildInfo>[];
...@@ -143,7 +122,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -143,7 +122,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
} }
@override @override
bool get supported => _platform.isMacOS; bool get supported => platform.isMacOS;
@override @override
Future<void> validateCommand() async { Future<void> validateCommand() async {
...@@ -152,14 +131,94 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -152,14 +131,94 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
throwToolExit('Building frameworks for iOS is only supported on the Mac.'); throwToolExit('Building frameworks for iOS is only supported on the Mac.');
} }
if (boolArgDeprecated('universal')) {
throwToolExit('--universal has been deprecated, only XCFrameworks are supported.');
}
if ((await getBuildInfos()).isEmpty) { if ((await getBuildInfos()).isEmpty) {
throwToolExit('At least one of "--debug" or "--profile", or "--release" is required.'); throwToolExit('At least one of "--debug" or "--profile", or "--release" is required.');
} }
} }
static Future<void> produceXCFramework(
Iterable<Directory> frameworks,
String frameworkBinaryName,
Directory outputDirectory,
ProcessManager processManager,
) async {
final List<String> xcframeworkCommand = <String>[
'xcrun',
'xcodebuild',
'-create-xcframework',
for (Directory framework in frameworks) ...<String>[
'-framework',
framework.path,
...framework.parent
.listSync()
.where((FileSystemEntity entity) =>
entity.basename.endsWith('bcsymbolmap') || entity.basename.endsWith('dSYM'))
.map((FileSystemEntity entity) => <String>['-debug-symbols', entity.path])
.expand<String>((List<String> parameter) => parameter),
],
'-output',
outputDirectory.childDirectory('$frameworkBinaryName.xcframework').path,
];
final ProcessResult xcframeworkResult = await processManager.run(
xcframeworkCommand,
);
if (xcframeworkResult.exitCode != 0) {
throwToolExit('Unable to create $frameworkBinaryName.xcframework: ${xcframeworkResult.stderr}');
}
}
}
/// Produces a .framework for integration into a host iOS app. The .framework
/// contains the Flutter engine and framework code as well as plugins. It can
/// be integrated into plain Xcode projects without using or other package
/// managers.
class BuildIOSFrameworkCommand extends BuildFrameworkCommand {
BuildIOSFrameworkCommand({
super.flutterVersion,
required super.buildSystem,
required bool verboseHelp,
super.cache,
super.platform,
}) : super(verboseHelp: verboseHelp) {
usesFlavorOption();
argParser
..addFlag('universal',
help: '(deprecated) Produce universal frameworks that include all valid architectures.',
hide: !verboseHelp,
)
..addFlag('xcframework',
help: 'Produce xcframeworks that include all valid architectures.',
negatable: false,
defaultsTo: true,
hide: !verboseHelp,
);
}
@override
final String name = 'ios-framework';
@override
final String description = 'Produces .xcframeworks for a Flutter project '
'and its plugins for integration into existing, plain iOS Xcode projects.\n'
'This can only be run on macOS hosts.';
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.iOS,
};
@override
Future<void> validateCommand() async {
await super.validateCommand();
if (boolArgDeprecated('universal')) {
throwToolExit('--universal has been deprecated, only XCFrameworks are supported.');
}
}
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
final String outputArgument = stringArgDeprecated('output') final String outputArgument = stringArgDeprecated('output')
...@@ -169,7 +228,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -169,7 +228,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
throwToolExit('--output is required.'); throwToolExit('--output is required.');
} }
if (!_project.ios.existsSync()) { if (!project.ios.existsSync()) {
throwToolExit('Project does not support iOS'); throwToolExit('Project does not support iOS');
} }
...@@ -177,7 +236,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -177,7 +236,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
final List<BuildInfo> buildInfos = await getBuildInfos(); final List<BuildInfo> buildInfos = await getBuildInfos();
displayNullSafetyMode(buildInfos.first); displayNullSafetyMode(buildInfos.first);
for (final BuildInfo buildInfo in buildInfos) { for (final BuildInfo buildInfo in buildInfos) {
final String? productBundleIdentifier = await _project.ios.productBundleIdentifier(buildInfo); final String? productBundleIdentifier = await project.ios.productBundleIdentifier(buildInfo);
globals.printStatus('Building frameworks for $productBundleIdentifier in ${getNameForBuildMode(buildInfo.mode)} mode...'); globals.printStatus('Building frameworks for $productBundleIdentifier in ${getNameForBuildMode(buildInfo.mode)} mode...');
final String xcodeBuildConfiguration = sentenceCase(getNameForBuildMode(buildInfo.mode)); final String xcodeBuildConfiguration = sentenceCase(getNameForBuildMode(buildInfo.mode));
final Directory modeDirectory = outputDirectory.childDirectory(xcodeBuildConfiguration); final Directory modeDirectory = outputDirectory.childDirectory(xcodeBuildConfiguration);
...@@ -202,9 +261,9 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -202,9 +261,9 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
buildInfo, modeDirectory, iPhoneBuildOutput, simulatorBuildOutput); buildInfo, modeDirectory, iPhoneBuildOutput, simulatorBuildOutput);
// Build and copy plugins. // Build and copy plugins.
await processPodsIfNeeded(_project.ios, getIosBuildDirectory(), buildInfo.mode); await processPodsIfNeeded(project.ios, getIosBuildDirectory(), buildInfo.mode);
if (hasPlugins(_project)) { if (hasPlugins(project)) {
await _producePlugins(buildInfo.mode, xcodeBuildConfiguration, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory, outputDirectory); await _producePlugins(buildInfo.mode, xcodeBuildConfiguration, iPhoneBuildOutput, simulatorBuildOutput, modeDirectory);
} }
final Status status = globals.logger.startProgress( final Status status = globals.logger.startProgress(
...@@ -225,12 +284,12 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -225,12 +284,12 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
globals.printStatus('Frameworks written to ${outputDirectory.path}.'); globals.printStatus('Frameworks written to ${outputDirectory.path}.');
if (!_project.isModule && hasPlugins(_project)) { if (!project.isModule && hasPlugins(project)) {
// Apps do not generate a FlutterPluginRegistrant.framework. Users will need // Apps do not generate a FlutterPluginRegistrant.framework. Users will need
// to copy the GeneratedPluginRegistrant class to their project manually. // to copy the GeneratedPluginRegistrant class to their project manually.
final File pluginRegistrantHeader = _project.ios.pluginRegistrantHeader; final File pluginRegistrantHeader = project.ios.pluginRegistrantHeader;
final File pluginRegistrantImplementation = final File pluginRegistrantImplementation =
_project.ios.pluginRegistrantImplementation; project.ios.pluginRegistrantImplementation;
pluginRegistrantHeader.copySync( pluginRegistrantHeader.copySync(
outputDirectory.childFile(pluginRegistrantHeader.basename).path); outputDirectory.childFile(pluginRegistrantHeader.basename).path);
pluginRegistrantImplementation.copySync(outputDirectory pluginRegistrantImplementation.copySync(outputDirectory
...@@ -250,10 +309,10 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -250,10 +309,10 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
void produceFlutterPodspec(BuildMode mode, Directory modeDirectory, { bool force = false }) { void produceFlutterPodspec(BuildMode mode, Directory modeDirectory, { bool force = false }) {
final Status status = globals.logger.startProgress(' ├─Creating Flutter.podspec...'); final Status status = globals.logger.startProgress(' ├─Creating Flutter.podspec...');
try { try {
final GitTagVersion gitTagVersion = _flutterVersion.gitTagVersion; final GitTagVersion gitTagVersion = flutterVersion.gitTagVersion;
if (!force && (gitTagVersion.x == null || gitTagVersion.y == null || gitTagVersion.z == null || gitTagVersion.commits != 0)) { if (!force && (gitTagVersion.x == null || gitTagVersion.y == null || gitTagVersion.z == null || gitTagVersion.commits != 0)) {
throwToolExit( throwToolExit(
'--cocoapods is only supported on the dev, beta, or stable channels. Detected version is ${_flutterVersion.frameworkVersion}'); '--cocoapods is only supported on the dev, beta, or stable channels. Detected version is ${flutterVersion.frameworkVersion}');
} }
// Podspecs use semantic versioning, which don't support hotfixes. // Podspecs use semantic versioning, which don't support hotfixes.
...@@ -262,7 +321,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -262,7 +321,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
// new artifacts when the source URL changes. // new artifacts when the source URL changes.
final int minorHotfixVersion = (gitTagVersion.z ?? 0) * 100 + (gitTagVersion.hotfix ?? 0); final int minorHotfixVersion = (gitTagVersion.z ?? 0) * 100 + (gitTagVersion.hotfix ?? 0);
final File license = _cache.getLicenseFile(); final File license = cache.getLicenseFile();
if (!license.existsSync()) { if (!license.existsSync()) {
throwToolExit('Could not find license at ${license.path}'); throwToolExit('Could not find license at ${license.path}');
} }
...@@ -272,7 +331,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -272,7 +331,7 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
final String podspecContents = ''' final String podspecContents = '''
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Flutter' s.name = 'Flutter'
s.version = '${gitTagVersion.x}.${gitTagVersion.y}.$minorHotfixVersion' # ${_flutterVersion.frameworkVersion} s.version = '${gitTagVersion.x}.${gitTagVersion.y}.$minorHotfixVersion' # ${flutterVersion.frameworkVersion}
s.summary = 'A UI toolkit for beautiful and fast apps.' s.summary = 'A UI toolkit for beautiful and fast apps.'
s.description = <<-DESC s.description = <<-DESC
Flutter is Google's UI toolkit for building beautiful, fast apps for mobile, web, desktop, and embedded devices from a single codebase. Flutter is Google's UI toolkit for building beautiful, fast apps for mobile, web, desktop, and embedded devices from a single codebase.
...@@ -285,7 +344,7 @@ $licenseSource ...@@ -285,7 +344,7 @@ $licenseSource
LICENSE LICENSE
} }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :http => '${_cache.storageBaseUrl}/flutter_infra_release/flutter/${_cache.engineRevision}/$artifactsMode/artifacts.zip' } s.source = { :http => '${cache.storageBaseUrl}/flutter_infra_release/flutter/${cache.engineRevision}/$artifactsMode/artifacts.zip' }
s.documentation_url = 'https://flutter.dev/docs' s.documentation_url = 'https://flutter.dev/docs'
s.platform = :ios, '11.0' s.platform = :ios, '11.0'
s.vendored_frameworks = 'Flutter.xcframework' s.vendored_frameworks = 'Flutter.xcframework'
...@@ -356,7 +415,7 @@ end ...@@ -356,7 +415,7 @@ end
final Environment environment = Environment( final Environment environment = Environment(
projectDir: globals.fs.currentDirectory, projectDir: globals.fs.currentDirectory,
outputDir: outputBuildDirectory, outputDir: outputBuildDirectory,
buildDir: _project.dartTool.childDirectory('flutter_build'), buildDir: project.dartTool.childDirectory('flutter_build'),
cacheDir: globals.cache.getRoot(), cacheDir: globals.cache.getRoot(),
flutterRootDir: globals.fs.directory(Cache.flutterRoot), flutterRootDir: globals.fs.directory(Cache.flutterRoot),
defines: <String, String>{ defines: <String, String>{
...@@ -401,7 +460,12 @@ end ...@@ -401,7 +460,12 @@ end
status.stop(); status.stop();
} }
await _produceXCFramework(frameworks, 'App', outputDirectory); await BuildFrameworkCommand.produceXCFramework(
frameworks,
'App',
outputDirectory,
globals.processManager,
);
} }
Future<void> _producePlugins( Future<void> _producePlugins(
...@@ -410,7 +474,6 @@ end ...@@ -410,7 +474,6 @@ end
Directory iPhoneBuildOutput, Directory iPhoneBuildOutput,
Directory simulatorBuildOutput, Directory simulatorBuildOutput,
Directory modeDirectory, Directory modeDirectory,
Directory outputDirectory,
) async { ) async {
final Status status = globals.logger.startProgress( final Status status = globals.logger.startProgress(
' ├─Building plugins...' ' ├─Building plugins...'
...@@ -437,7 +500,7 @@ end ...@@ -437,7 +500,7 @@ end
RunResult buildPluginsResult = await globals.processUtils.run( RunResult buildPluginsResult = await globals.processUtils.run(
pluginsBuildCommand, pluginsBuildCommand,
workingDirectory: _project.ios.hostAppRoot.childDirectory('Pods').path, workingDirectory: project.ios.hostAppRoot.childDirectory('Pods').path,
); );
if (buildPluginsResult.exitCode != 0) { if (buildPluginsResult.exitCode != 0) {
...@@ -464,7 +527,7 @@ end ...@@ -464,7 +527,7 @@ end
buildPluginsResult = await globals.processUtils.run( buildPluginsResult = await globals.processUtils.run(
pluginsBuildCommand, pluginsBuildCommand,
workingDirectory: _project.ios.hostAppRoot workingDirectory: project.ios.hostAppRoot
.childDirectory('Pods') .childDirectory('Pods')
.path, .path,
); );
...@@ -500,46 +563,16 @@ end ...@@ -500,46 +563,16 @@ end
.childDirectory(podFrameworkName), .childDirectory(podFrameworkName),
]; ];
await _produceXCFramework(frameworks, binaryName, modeDirectory); await BuildFrameworkCommand.produceXCFramework(
frameworks,
binaryName,
modeDirectory,
globals.processManager,
);
} }
} }
} finally { } finally {
status.stop(); status.stop();
} }
} }
Future<void> _produceXCFramework(Iterable<Directory> frameworks,
String frameworkBinaryName, Directory outputDirectory) async {
if (!boolArgDeprecated('xcframework')) {
return;
}
final List<String> xcframeworkCommand = <String>[
...globals.xcode!.xcrunCommand(),
'xcodebuild',
'-create-xcframework',
for (Directory framework in frameworks) ...<String>[
'-framework',
framework.path,
...framework.parent
.listSync()
.where((FileSystemEntity entity) =>
entity.basename.endsWith('bcsymbolmap') ||
entity.basename.endsWith('dSYM'))
.map((FileSystemEntity entity) =>
<String>['-debug-symbols', entity.path])
.expand<String>((List<String> parameter) => parameter),
],
'-output',
outputDirectory.childDirectory('$frameworkBinaryName.xcframework').path,
];
final RunResult xcframeworkResult = await globals.processUtils.run(
xcframeworkCommand,
);
if (xcframeworkResult.exitCode != 0) {
throwToolExit(
'Unable to create $frameworkBinaryName.xcframework: ${xcframeworkResult.stderr}');
}
}
} }
...@@ -271,4 +271,83 @@ void main() { ...@@ -271,4 +271,83 @@ void main() {
}); });
}); });
}); });
group('XCFrameworks', () {
MemoryFileSystem fileSystem;
FakeProcessManager fakeProcessManager;
setUp(() {
fileSystem = MemoryFileSystem.test();
fakeProcessManager = FakeProcessManager.empty();
});
testWithoutContext('created', () async {
final Directory frameworkA = fileSystem.directory('FrameworkA.framework')..createSync();
final Directory frameworkB = fileSystem.directory('FrameworkB.framework')..createSync();
final Directory output = fileSystem.directory('output');
fakeProcessManager.addCommand(FakeCommand(
command: <String>[
'xcrun',
'xcodebuild',
'-create-xcframework',
'-framework',
frameworkA.path,
'-framework',
frameworkB.path,
'-output',
output.childDirectory('Combine.xcframework').path,
],
));
await BuildFrameworkCommand.produceXCFramework(
<Directory>[frameworkA, frameworkB],
'Combine',
output,
fakeProcessManager,
);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('created with symbols', () async {
final Directory parentA = fileSystem.directory('FrameworkA')..createSync();
final File bcsymbolmapA = parentA.childFile('ABC123.bcsymbolmap')..createSync();
final File dSYMA = parentA.childFile('FrameworkA.framework.dSYM')..createSync();
final Directory frameworkA = parentA.childDirectory('FrameworkA.framework')..createSync();
final Directory parentB = fileSystem.directory('FrameworkB')..createSync();
final File bcsymbolmapB = parentB.childFile('ZYX987.bcsymbolmap')..createSync();
final File dSYMB = parentB.childFile('FrameworkB.framework.dSYM')..createSync();
final Directory frameworkB = parentB.childDirectory('FrameworkB.framework')..createSync();
final Directory output = fileSystem.directory('output');
fakeProcessManager.addCommand(FakeCommand(
command: <String>[
'xcrun',
'xcodebuild',
'-create-xcframework',
'-framework',
frameworkA.path,
'-debug-symbols',
bcsymbolmapA.path,
'-debug-symbols',
dSYMA.path,
'-framework',
frameworkB.path,
'-debug-symbols',
bcsymbolmapB.path,
'-debug-symbols',
dSYMB.path,
'-output',
output.childDirectory('Combine.xcframework').path,
],
));
await BuildFrameworkCommand.produceXCFramework(
<Directory>[frameworkA, frameworkB],
'Combine',
output,
fakeProcessManager,
);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
});
} }
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