Adopt Flutter.xcframework in tool (#71495)
This commit is contained in:
parent
f67b94bdf6
commit
d4150d3f6d
@ -102,6 +102,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
options: <String>[
|
options: <String>[
|
||||||
'ios-framework',
|
'ios-framework',
|
||||||
'--universal',
|
'--universal',
|
||||||
|
'--verbose',
|
||||||
'--output=$outputDirectoryName'
|
'--output=$outputDirectoryName'
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -164,16 +165,43 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
'App',
|
'App',
|
||||||
);
|
);
|
||||||
|
|
||||||
// This seemed easier than an explicit Xcode version check.
|
// Based on the locally installed version of Xcode.
|
||||||
String xcodeArmDirectoryName;
|
String localXcodeArmDirectoryName;
|
||||||
if (exists(File(xcode11AppFrameworkDirectory))) {
|
if (exists(File(xcode11AppFrameworkDirectory))) {
|
||||||
xcodeArmDirectoryName = xcode11ArmDirectoryName;
|
localXcodeArmDirectoryName = xcode11ArmDirectoryName;
|
||||||
} else if (exists(File(xcode12AppFrameworkDirectory))) {
|
} else if (exists(File(xcode12AppFrameworkDirectory))) {
|
||||||
xcodeArmDirectoryName = xcode12ArmDirectoryName;
|
localXcodeArmDirectoryName = xcode12ArmDirectoryName;
|
||||||
} else {
|
} else {
|
||||||
throw const FileSystemException('Expected App.framework binary to exist.');
|
throw const FileSystemException('Expected App.framework binary to exist.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String xcode11FlutterFrameworkDirectory = path.join(
|
||||||
|
outputPath,
|
||||||
|
'Debug',
|
||||||
|
'Flutter.xcframework',
|
||||||
|
xcode11ArmDirectoryName,
|
||||||
|
'Flutter.framework',
|
||||||
|
'Flutter',
|
||||||
|
);
|
||||||
|
final String xcode12FlutterFrameworkDirectory = path.join(
|
||||||
|
outputPath,
|
||||||
|
'Debug',
|
||||||
|
'Flutter.xcframework',
|
||||||
|
xcode12ArmDirectoryName,
|
||||||
|
'Flutter.framework',
|
||||||
|
'Flutter',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Based on the version of Xcode installed on the engine builder.
|
||||||
|
String builderXcodeArmDirectoryName;
|
||||||
|
if (exists(File(xcode11FlutterFrameworkDirectory))) {
|
||||||
|
builderXcodeArmDirectoryName = xcode11ArmDirectoryName;
|
||||||
|
} else if (exists(File(xcode12FlutterFrameworkDirectory))) {
|
||||||
|
builderXcodeArmDirectoryName = xcode12ArmDirectoryName;
|
||||||
|
} else {
|
||||||
|
throw const FileSystemException('Expected Flutter.framework binary to exist.');
|
||||||
|
}
|
||||||
|
|
||||||
checkFileExists(path.join(
|
checkFileExists(path.join(
|
||||||
outputPath,
|
outputPath,
|
||||||
'Debug',
|
'Debug',
|
||||||
@ -214,7 +242,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'App.xcframework',
|
'App.xcframework',
|
||||||
xcodeArmDirectoryName,
|
localXcodeArmDirectoryName,
|
||||||
'App.framework',
|
'App.framework',
|
||||||
'App',
|
'App',
|
||||||
));
|
));
|
||||||
@ -239,30 +267,25 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
'Flutter',
|
'Flutter',
|
||||||
);
|
);
|
||||||
|
|
||||||
await _checkFrameworkArchs(engineFrameworkPath, mode == 'Debug');
|
await _checkFrameworkArchs(engineFrameworkPath, true);
|
||||||
await _checkBitcode(engineFrameworkPath, mode);
|
await _checkBitcode(engineFrameworkPath, mode);
|
||||||
|
|
||||||
checkFileExists(path.join(
|
checkFileExists(path.join(
|
||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'Flutter.xcframework',
|
'Flutter.xcframework',
|
||||||
xcodeArmDirectoryName,
|
builderXcodeArmDirectoryName,
|
||||||
'Flutter.framework',
|
'Flutter.framework',
|
||||||
'Flutter',
|
'Flutter',
|
||||||
));
|
));
|
||||||
final String simulatorFrameworkPath = path.join(
|
checkFileExists(path.join(
|
||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'Flutter.xcframework',
|
'Flutter.xcframework',
|
||||||
'ios-x86_64-simulator',
|
'ios-x86_64-simulator',
|
||||||
'Flutter.framework',
|
'Flutter.framework',
|
||||||
'Flutter',
|
'Flutter',
|
||||||
);
|
));
|
||||||
if (mode == 'Debug') {
|
|
||||||
checkFileExists(simulatorFrameworkPath);
|
|
||||||
} else {
|
|
||||||
checkFileNotExists(simulatorFrameworkPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section("Check all modes' engine header");
|
section("Check all modes' engine header");
|
||||||
@ -287,7 +310,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'device_info.xcframework',
|
'device_info.xcframework',
|
||||||
xcodeArmDirectoryName,
|
localXcodeArmDirectoryName,
|
||||||
'device_info.framework',
|
'device_info.framework',
|
||||||
'device_info',
|
'device_info',
|
||||||
));
|
));
|
||||||
@ -296,7 +319,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'device_info.xcframework',
|
'device_info.xcframework',
|
||||||
xcodeArmDirectoryName,
|
localXcodeArmDirectoryName,
|
||||||
'device_info.framework',
|
'device_info.framework',
|
||||||
'Headers',
|
'Headers',
|
||||||
'DeviceInfoPlugin.h',
|
'DeviceInfoPlugin.h',
|
||||||
@ -357,7 +380,7 @@ Future<void> _testBuildIosFramework(Directory projectDir, { bool isModule = fals
|
|||||||
outputPath,
|
outputPath,
|
||||||
mode,
|
mode,
|
||||||
'FlutterPluginRegistrant.xcframework',
|
'FlutterPluginRegistrant.xcframework',
|
||||||
xcodeArmDirectoryName,
|
localXcodeArmDirectoryName,
|
||||||
'FlutterPluginRegistrant.framework',
|
'FlutterPluginRegistrant.framework',
|
||||||
'Headers',
|
'Headers',
|
||||||
'GeneratedPluginRegistrant.h',
|
'GeneratedPluginRegistrant.h',
|
||||||
|
@ -22,6 +22,8 @@ Future<bool> containsBitcode(String pathToBinary) async {
|
|||||||
// See: https://stackoverflow.com/questions/32755775/how-to-check-a-static-library-is-built-contain-bitcode
|
// See: https://stackoverflow.com/questions/32755775/how-to-check-a-static-library-is-built-contain-bitcode
|
||||||
final String loadCommands = await eval('otool', <String>[
|
final String loadCommands = await eval('otool', <String>[
|
||||||
'-l',
|
'-l',
|
||||||
|
'-arch',
|
||||||
|
'arm64',
|
||||||
pathToBinary,
|
pathToBinary,
|
||||||
]);
|
]);
|
||||||
if (!loadCommands.contains('__LLVM')) {
|
if (!loadCommands.contains('__LLVM')) {
|
||||||
|
@ -35,13 +35,27 @@ def flutter_additional_ios_build_settings(target)
|
|||||||
# This podhelper script is at $FLUTTER_ROOT/packages/flutter_tools/bin.
|
# This podhelper script is at $FLUTTER_ROOT/packages/flutter_tools/bin.
|
||||||
# Add search paths from $FLUTTER_ROOT/bin/cache/artifacts/engine.
|
# Add search paths from $FLUTTER_ROOT/bin/cache/artifacts/engine.
|
||||||
artifacts_dir = File.join('..', '..', '..', '..', 'bin', 'cache', 'artifacts', 'engine')
|
artifacts_dir = File.join('..', '..', '..', '..', 'bin', 'cache', 'artifacts', 'engine')
|
||||||
debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios'), __FILE__)
|
debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios', 'Flutter.xcframework'), __FILE__)
|
||||||
release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release'), __FILE__)
|
|
||||||
|
unless Dir.exist?(debug_framework_dir)
|
||||||
|
# iOS artifacts have not been downloaded.
|
||||||
|
raise "#{debug_framework_dir} must exist. If you're running pod install manually, make sure flutter build ios is executed first"
|
||||||
|
end
|
||||||
|
|
||||||
|
release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release', 'Flutter.xcframework'), __FILE__)
|
||||||
|
|
||||||
target.build_configurations.each do |build_configuration|
|
target.build_configurations.each do |build_configuration|
|
||||||
# Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only).
|
# Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only).
|
||||||
configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir
|
configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir
|
||||||
build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS'] = "\"#{configuration_engine_dir}\" $(inherited)"
|
Dir.new(configuration_engine_dir).each_child do |xcframework_file|
|
||||||
|
if xcframework_file.end_with?("-simulator") # ios-x86_64-simulator
|
||||||
|
build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)"
|
||||||
|
elsif xcframework_file.start_with?("ios-") # ios-armv7_arm64
|
||||||
|
build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)"
|
||||||
|
else
|
||||||
|
# Info.plist or another platform.
|
||||||
|
end
|
||||||
|
end
|
||||||
build_configuration.build_settings['OTHER_LDFLAGS'] = '$(inherited) -framework Flutter'
|
build_configuration.build_settings['OTHER_LDFLAGS'] = '$(inherited) -framework Flutter'
|
||||||
|
|
||||||
build_configuration.build_settings['CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER'] = 'NO'
|
build_configuration.build_settings['CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER'] = 'NO'
|
||||||
|
@ -115,7 +115,7 @@ is set to release or run \"flutter build ios --release\", then re-run Archive fr
|
|||||||
local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}"
|
local framework_path="${FLUTTER_ROOT}/bin/cache/artifacts/engine/${artifact_variant}"
|
||||||
local flutter_engine_flag=""
|
local flutter_engine_flag=""
|
||||||
local local_engine_flag=""
|
local local_engine_flag=""
|
||||||
local flutter_framework="${framework_path}/Flutter.framework"
|
local flutter_framework="${framework_path}/Flutter.xcframework"
|
||||||
|
|
||||||
if [[ -n "$FLUTTER_ENGINE" ]]; then
|
if [[ -n "$FLUTTER_ENGINE" ]]; then
|
||||||
flutter_engine_flag="--local-engine-src-path=${FLUTTER_ENGINE}"
|
flutter_engine_flag="--local-engine-src-path=${FLUTTER_ENGINE}"
|
||||||
@ -135,7 +135,7 @@ is set to release or run \"flutter build ios --release\", then re-run Archive fr
|
|||||||
exit -1
|
exit -1
|
||||||
fi
|
fi
|
||||||
local_engine_flag="--local-engine=${LOCAL_ENGINE}"
|
local_engine_flag="--local-engine=${LOCAL_ENGINE}"
|
||||||
flutter_framework="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.framework"
|
flutter_framework="${FLUTTER_ENGINE}/out/${LOCAL_ENGINE}/Flutter.xcframework"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local bitcode_flag=""
|
local bitcode_flag=""
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:process/process.dart';
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
|
import 'base/common.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/platform.dart';
|
import 'base/platform.dart';
|
||||||
import 'base/utils.dart';
|
import 'base/utils.dart';
|
||||||
@ -305,12 +306,14 @@ class CachedArtifacts implements Artifacts {
|
|||||||
BuildMode mode, EnvironmentType environmentType) {
|
BuildMode mode, EnvironmentType environmentType) {
|
||||||
switch (artifact) {
|
switch (artifact) {
|
||||||
case Artifact.genSnapshot:
|
case Artifact.genSnapshot:
|
||||||
case Artifact.flutterFramework:
|
|
||||||
case Artifact.flutterXcframework:
|
case Artifact.flutterXcframework:
|
||||||
case Artifact.frontendServerSnapshotForEngineDartSdk:
|
case Artifact.frontendServerSnapshotForEngineDartSdk:
|
||||||
final String artifactFileName = _artifactToFileName(artifact);
|
final String artifactFileName = _artifactToFileName(artifact);
|
||||||
final String engineDir = _getEngineArtifactsPath(platform, mode);
|
final String engineDir = _getEngineArtifactsPath(platform, mode);
|
||||||
return _fileSystem.path.join(engineDir, artifactFileName);
|
return _fileSystem.path.join(engineDir, artifactFileName);
|
||||||
|
case Artifact.flutterFramework:
|
||||||
|
final String engineDir = _getEngineArtifactsPath(platform, mode);
|
||||||
|
return _getIosEngineArtifactPath(engineDir, environmentType, _fileSystem);
|
||||||
case Artifact.idevicescreenshot:
|
case Artifact.idevicescreenshot:
|
||||||
case Artifact.idevicesyslog:
|
case Artifact.idevicesyslog:
|
||||||
final String artifactFileName = _artifactToFileName(artifact);
|
final String artifactFileName = _artifactToFileName(artifact);
|
||||||
@ -527,6 +530,38 @@ HostPlatform _currentHostPlatformAsHost(Platform platform) {
|
|||||||
throw UnimplementedError('Host OS not supported.');
|
throw UnimplementedError('Host OS not supported.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _getIosEngineArtifactPath(String engineDirectory,
|
||||||
|
EnvironmentType environmentType, FileSystem fileSystem) {
|
||||||
|
final Directory xcframeworkDirectory = fileSystem
|
||||||
|
.directory(engineDirectory)
|
||||||
|
.childDirectory(_artifactToFileName(Artifact.flutterXcframework));
|
||||||
|
|
||||||
|
if (!xcframeworkDirectory.existsSync()) {
|
||||||
|
throwToolExit('No xcframework found at ${xcframeworkDirectory.path}. Try running "flutter build ios".');
|
||||||
|
}
|
||||||
|
Directory flutterFrameworkSource;
|
||||||
|
for (final Directory platformDirectory
|
||||||
|
in xcframeworkDirectory.listSync().whereType<Directory>()) {
|
||||||
|
if (!platformDirectory.basename.startsWith('ios-')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// ios-x86_64-simulator, ios-armv7_arm64 (Xcode 11), or ios-arm64_armv7 (Xcode 12).
|
||||||
|
final bool simulatorDirectory =
|
||||||
|
platformDirectory.basename.endsWith('-simulator');
|
||||||
|
if ((environmentType == EnvironmentType.simulator && simulatorDirectory) ||
|
||||||
|
(environmentType == EnvironmentType.physical && !simulatorDirectory)) {
|
||||||
|
flutterFrameworkSource = platformDirectory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flutterFrameworkSource == null) {
|
||||||
|
throwToolExit('No iOS frameworks found in ${xcframeworkDirectory.path}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return flutterFrameworkSource
|
||||||
|
.childDirectory(_artifactToFileName(Artifact.flutterFramework))
|
||||||
|
.path;
|
||||||
|
}
|
||||||
|
|
||||||
/// Manages the artifacts of a locally built engine.
|
/// Manages the artifacts of a locally built engine.
|
||||||
class LocalEngineArtifacts implements Artifacts {
|
class LocalEngineArtifacts implements Artifacts {
|
||||||
LocalEngineArtifacts(
|
LocalEngineArtifacts(
|
||||||
@ -578,7 +613,8 @@ class LocalEngineArtifacts implements Artifacts {
|
|||||||
case Artifact.platformLibrariesJson:
|
case Artifact.platformLibrariesJson:
|
||||||
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), 'lib', artifactFileName);
|
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), 'lib', artifactFileName);
|
||||||
case Artifact.flutterFramework:
|
case Artifact.flutterFramework:
|
||||||
return _fileSystem.path.join(engineOutPath, artifactFileName);
|
return _getIosEngineArtifactPath(
|
||||||
|
engineOutPath, environmentType, _fileSystem);
|
||||||
case Artifact.flutterPatchedSdkPath:
|
case Artifact.flutterPatchedSdkPath:
|
||||||
// When using local engine always use [BuildMode.debug] regardless of
|
// When using local engine always use [BuildMode.debug] regardless of
|
||||||
// what was specified in [mode] argument because local engine will
|
// what was specified in [mode] argument because local engine will
|
||||||
|
@ -249,7 +249,7 @@ abstract class UnpackIOS extends Target {
|
|||||||
const Source.pattern(
|
const Source.pattern(
|
||||||
'{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/ios.dart'),
|
'{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/ios.dart'),
|
||||||
Source.artifact(
|
Source.artifact(
|
||||||
Artifact.flutterFramework,
|
Artifact.flutterXcframework,
|
||||||
platform: TargetPlatform.ios,
|
platform: TargetPlatform.ios,
|
||||||
mode: buildMode,
|
mode: buildMode,
|
||||||
),
|
),
|
||||||
|
@ -924,14 +924,11 @@ abstract class EngineCachedArtifact extends CachedArtifact {
|
|||||||
|
|
||||||
_makeFilesExecutable(dir, operatingSystemUtils);
|
_makeFilesExecutable(dir, operatingSystemUtils);
|
||||||
|
|
||||||
const List<String> frameworkNames = <String>['Flutter', 'FlutterMacOS'];
|
final File frameworkZip = fileSystem.file(fileSystem.path.join(dir.path, 'FlutterMacOS.framework.zip'));
|
||||||
for (final String frameworkName in frameworkNames) {
|
if (frameworkZip.existsSync()) {
|
||||||
final File frameworkZip = fileSystem.file(fileSystem.path.join(dir.path, '$frameworkName.framework.zip'));
|
final Directory framework = fileSystem.directory(fileSystem.path.join(dir.path, 'FlutterMacOS.framework'));
|
||||||
if (frameworkZip.existsSync()) {
|
framework.createSync();
|
||||||
final Directory framework = fileSystem.directory(fileSystem.path.join(dir.path, '$frameworkName.framework'));
|
operatingSystemUtils.unzip(frameworkZip, framework);
|
||||||
framework.createSync();
|
|
||||||
operatingSystemUtils.unzip(frameworkZip, framework);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,10 +295,7 @@ LICENSE
|
|||||||
s.source = { :http => '${_cache.storageBaseUrl}/flutter_infra/flutter/${_cache.engineRevision}/$artifactsMode/artifacts.zip' }
|
s.source = { :http => '${_cache.storageBaseUrl}/flutter_infra/flutter/${_cache.engineRevision}/$artifactsMode/artifacts.zip' }
|
||||||
s.documentation_url = 'https://flutter.dev/docs'
|
s.documentation_url = 'https://flutter.dev/docs'
|
||||||
s.platform = :ios, '8.0'
|
s.platform = :ios, '8.0'
|
||||||
s.vendored_frameworks = 'Flutter.framework'
|
s.vendored_frameworks = 'Flutter.xcframework'
|
||||||
s.prepare_command = <<-CMD
|
|
||||||
unzip Flutter.framework -d Flutter.framework
|
|
||||||
CMD
|
|
||||||
end
|
end
|
||||||
''';
|
''';
|
||||||
|
|
||||||
@ -314,56 +311,31 @@ end
|
|||||||
Directory modeDirectory,
|
Directory modeDirectory,
|
||||||
) async {
|
) async {
|
||||||
final Status status = globals.logger.startProgress(
|
final Status status = globals.logger.startProgress(
|
||||||
' ├─Populating Flutter.framework...',
|
' ├─Populating Flutter.xcframework...',
|
||||||
);
|
);
|
||||||
final String engineCacheFlutterFrameworkDirectory = globals.artifacts.getArtifactPath(
|
final String engineCacheFlutterFrameworkDirectory = globals.artifacts.getArtifactPath(
|
||||||
Artifact.flutterFramework,
|
Artifact.flutterXcframework,
|
||||||
platform: TargetPlatform.ios,
|
platform: TargetPlatform.ios,
|
||||||
mode: buildInfo.mode,
|
mode: buildInfo.mode,
|
||||||
);
|
);
|
||||||
final String flutterFrameworkFileName = globals.fs.path.basename(
|
final String flutterFrameworkFileName = globals.fs.path.basename(
|
||||||
engineCacheFlutterFrameworkDirectory,
|
engineCacheFlutterFrameworkDirectory,
|
||||||
);
|
);
|
||||||
final Directory fatFlutterFrameworkCopy = modeDirectory.childDirectory(
|
final Directory flutterFrameworkCopy = modeDirectory.childDirectory(
|
||||||
flutterFrameworkFileName,
|
flutterFrameworkFileName,
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Copy universal engine cache framework to mode directory.
|
// Copy xcframework engine cache framework to mode directory.
|
||||||
globals.fsUtils.copyDirectorySync(
|
globals.fsUtils.copyDirectorySync(
|
||||||
globals.fs.directory(engineCacheFlutterFrameworkDirectory),
|
globals.fs.directory(engineCacheFlutterFrameworkDirectory),
|
||||||
fatFlutterFrameworkCopy,
|
flutterFrameworkCopy,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (buildInfo.mode != BuildMode.debug) {
|
|
||||||
final File fatFlutterFrameworkBinary = fatFlutterFrameworkCopy.childFile('Flutter');
|
|
||||||
|
|
||||||
// Remove simulator architecture in profile and release mode.
|
|
||||||
final List<String> lipoCommand = <String>[
|
|
||||||
...globals.xcode.xcrunCommand(),
|
|
||||||
'lipo',
|
|
||||||
fatFlutterFrameworkBinary.path,
|
|
||||||
'-remove',
|
|
||||||
'x86_64',
|
|
||||||
'-output',
|
|
||||||
fatFlutterFrameworkBinary.path
|
|
||||||
];
|
|
||||||
final RunResult lipoResult = await globals.processUtils.run(
|
|
||||||
lipoCommand,
|
|
||||||
allowReentrantFlutter: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (lipoResult.exitCode != 0) {
|
|
||||||
throwToolExit(
|
|
||||||
'Unable to remove simulator architecture in ${buildInfo.mode}: ${lipoResult.stderr}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
status.stop();
|
status.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _produceXCFrameworkFromUniversal(buildInfo, fatFlutterFrameworkCopy);
|
await _produceUniversalFromXCFramework(buildInfo, flutterFrameworkCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _produceAppFramework(
|
Future<void> _produceAppFramework(
|
||||||
@ -558,112 +530,34 @@ end
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _produceXCFrameworkFromUniversal(BuildInfo buildInfo, Directory fatFramework) async {
|
Future<void> _produceUniversalFromXCFramework(BuildInfo buildInfo, Directory xcframework) async {
|
||||||
if (boolArg('xcframework')) {
|
if (boolArg('universal')) {
|
||||||
final String frameworkBinaryName = globals.fs.path.basenameWithoutExtension(
|
final String frameworkBinaryName =
|
||||||
fatFramework.basename);
|
globals.fs.path.basenameWithoutExtension(xcframework.basename);
|
||||||
|
|
||||||
final Status status = globals.logger.startProgress(
|
final Status status = globals.logger.startProgress(
|
||||||
' ├─Creating $frameworkBinaryName.xcframework...',
|
' ├─Creating $frameworkBinaryName.framework...',
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
if (buildInfo.mode == BuildMode.debug) {
|
final Iterable<Directory> frameworks = xcframework
|
||||||
await _produceDebugXCFramework(fatFramework, frameworkBinaryName);
|
.listSync()
|
||||||
} else {
|
.whereType<Directory>()
|
||||||
await _produceXCFramework(
|
.map((Directory triple) => triple
|
||||||
<Directory>[fatFramework], frameworkBinaryName,
|
.listSync()
|
||||||
fatFramework.parent);
|
.whereType<Directory>()
|
||||||
}
|
.firstWhere((Directory frameworkDirectory) =>
|
||||||
|
frameworkDirectory.basename ==
|
||||||
|
'$frameworkBinaryName.framework'));
|
||||||
|
|
||||||
|
await _produceUniversalFramework(
|
||||||
|
frameworks, frameworkBinaryName, xcframework.parent);
|
||||||
} finally {
|
} finally {
|
||||||
status.stop();
|
status.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!boolArg('universal')) {
|
if (!boolArg('xcframework')) {
|
||||||
fatFramework.deleteSync(recursive: true);
|
xcframework.deleteSync(recursive: true);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _produceDebugXCFramework(Directory fatFramework, String frameworkBinaryName) async {
|
|
||||||
final String frameworkFileName = fatFramework.basename;
|
|
||||||
final File fatFlutterFrameworkBinary = fatFramework.childFile(
|
|
||||||
frameworkBinaryName,
|
|
||||||
);
|
|
||||||
final Directory temporaryOutput = globals.fs.systemTempDirectory.createTempSync(
|
|
||||||
'flutter_tool_build_ios_framework.',
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
// Copy universal framework to variant directory.
|
|
||||||
final Directory iPhoneBuildOutput = temporaryOutput.childDirectory(
|
|
||||||
'ios',
|
|
||||||
)..createSync(recursive: true);
|
|
||||||
final Directory simulatorBuildOutput = temporaryOutput.childDirectory(
|
|
||||||
'simulator',
|
|
||||||
)..createSync(recursive: true);
|
|
||||||
final Directory armFlutterFrameworkDirectory = iPhoneBuildOutput
|
|
||||||
.childDirectory(frameworkFileName);
|
|
||||||
final File armFlutterFrameworkBinary = armFlutterFrameworkDirectory
|
|
||||||
.childFile(frameworkBinaryName);
|
|
||||||
globals.fsUtils.copyDirectorySync(fatFramework, armFlutterFrameworkDirectory);
|
|
||||||
|
|
||||||
// Create iOS framework.
|
|
||||||
List<String> lipoCommand = <String>[
|
|
||||||
...globals.xcode.xcrunCommand(),
|
|
||||||
'lipo',
|
|
||||||
fatFlutterFrameworkBinary.path,
|
|
||||||
'-remove',
|
|
||||||
'x86_64',
|
|
||||||
'-output',
|
|
||||||
armFlutterFrameworkBinary.path
|
|
||||||
];
|
|
||||||
|
|
||||||
RunResult lipoResult = await globals.processUtils.run(
|
|
||||||
lipoCommand,
|
|
||||||
allowReentrantFlutter: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (lipoResult.exitCode != 0) {
|
|
||||||
throwToolExit('Unable to create ARM framework: ${lipoResult.stderr}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create simulator framework.
|
|
||||||
final Directory simulatorFlutterFrameworkDirectory = simulatorBuildOutput
|
|
||||||
.childDirectory(frameworkFileName);
|
|
||||||
final File simulatorFlutterFrameworkBinary = simulatorFlutterFrameworkDirectory
|
|
||||||
.childFile(frameworkBinaryName);
|
|
||||||
globals.fsUtils.copyDirectorySync(fatFramework, simulatorFlutterFrameworkDirectory);
|
|
||||||
|
|
||||||
lipoCommand = <String>[
|
|
||||||
...globals.xcode.xcrunCommand(),
|
|
||||||
'lipo',
|
|
||||||
fatFlutterFrameworkBinary.path,
|
|
||||||
'-thin',
|
|
||||||
'x86_64',
|
|
||||||
'-output',
|
|
||||||
simulatorFlutterFrameworkBinary.path
|
|
||||||
];
|
|
||||||
|
|
||||||
lipoResult = await globals.processUtils.run(
|
|
||||||
lipoCommand,
|
|
||||||
allowReentrantFlutter: false,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (lipoResult.exitCode != 0) {
|
|
||||||
throwToolExit(
|
|
||||||
'Unable to create simulator framework: ${lipoResult.stderr}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create XCFramework from iOS and simulator frameworks.
|
|
||||||
await _produceXCFramework(
|
|
||||||
<Directory>[
|
|
||||||
armFlutterFrameworkDirectory,
|
|
||||||
simulatorFlutterFrameworkDirectory
|
|
||||||
],
|
|
||||||
frameworkBinaryName,
|
|
||||||
fatFramework.parent,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
temporaryOutput.deleteSync(recursive: true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,16 +13,14 @@ import '../macos/xcode.dart';
|
|||||||
|
|
||||||
const bool kBitcodeEnabledDefault = false;
|
const bool kBitcodeEnabledDefault = false;
|
||||||
|
|
||||||
Future<void> validateBitcode(BuildMode buildMode, TargetPlatform targetPlatform) async {
|
Future<void> validateBitcode(BuildMode buildMode, TargetPlatform targetPlatform, EnvironmentType environmentType) async {
|
||||||
final Artifacts localArtifacts = globals.artifacts;
|
final Artifacts localArtifacts = globals.artifacts;
|
||||||
final String flutterFrameworkPath = localArtifacts.getArtifactPath(
|
final String flutterFrameworkPath = localArtifacts.getArtifactPath(
|
||||||
Artifact.flutterFramework,
|
Artifact.flutterFramework,
|
||||||
mode: buildMode,
|
mode: buildMode,
|
||||||
platform: targetPlatform,
|
platform: targetPlatform,
|
||||||
|
environmentType: environmentType,
|
||||||
);
|
);
|
||||||
if (!globals.fs.isDirectorySync(flutterFrameworkPath)) {
|
|
||||||
throwToolExit('Flutter.framework not found at $flutterFrameworkPath');
|
|
||||||
}
|
|
||||||
final Xcode xcode = context.get<Xcode>();
|
final Xcode xcode = context.get<Xcode>();
|
||||||
|
|
||||||
final RunResult clangResult = await xcode.clang(<String>['--version']);
|
final RunResult clangResult = await xcode.clang(<String>['--version']);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import '../base/fingerprint.dart';
|
import '../base/fingerprint.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
|
import '../cache.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals.dart' as globals;
|
||||||
import '../plugins.dart';
|
import '../plugins.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
@ -28,6 +29,13 @@ Future<void> processPodsIfNeeded(
|
|||||||
xcodeProject.xcodeProjectInfoFile.path,
|
xcodeProject.xcodeProjectInfoFile.path,
|
||||||
xcodeProject.podfile.path,
|
xcodeProject.podfile.path,
|
||||||
xcodeProject.generatedXcodePropertiesFile.path,
|
xcodeProject.generatedXcodePropertiesFile.path,
|
||||||
|
globals.fs.path.join(
|
||||||
|
Cache.flutterRoot,
|
||||||
|
'packages',
|
||||||
|
'flutter_tools',
|
||||||
|
'bin',
|
||||||
|
'podhelper.rb',
|
||||||
|
),
|
||||||
],
|
],
|
||||||
fileSystem: globals.fs,
|
fileSystem: globals.fs,
|
||||||
logger: globals.logger,
|
logger: globals.logger,
|
||||||
|
@ -659,7 +659,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
// to be in this location.
|
// to be in this location.
|
||||||
final Directory framework = globals.fs.directory(
|
final Directory framework = globals.fs.directory(
|
||||||
globals.artifacts.getArtifactPath(
|
globals.artifacts.getArtifactPath(
|
||||||
Artifact.flutterFramework,
|
Artifact.flutterXcframework,
|
||||||
platform: TargetPlatform.ios,
|
platform: TargetPlatform.ios,
|
||||||
mode: mode,
|
mode: mode,
|
||||||
environmentType: environmentType,
|
environmentType: environmentType,
|
||||||
@ -668,7 +668,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
|
|||||||
if (framework.existsSync()) {
|
if (framework.existsSync()) {
|
||||||
globals.fsUtils.copyDirectorySync(
|
globals.fsUtils.copyDirectorySync(
|
||||||
framework,
|
framework,
|
||||||
engineCopyDirectory.childDirectory('Flutter.framework'),
|
engineCopyDirectory.childDirectory('Flutter.xcframework'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,5 +14,5 @@ Flutter provides an easy and productive way to build and deploy high-performance
|
|||||||
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 = '8.0'
|
s.ios.deployment_target = '8.0'
|
||||||
s.vendored_frameworks = 'Flutter.framework'
|
s.vendored_frameworks = 'Flutter.xcframework'
|
||||||
end
|
end
|
||||||
|
@ -30,7 +30,7 @@ end
|
|||||||
def install_flutter_engine_pod
|
def install_flutter_engine_pod
|
||||||
current_directory = File.expand_path('..', __FILE__)
|
current_directory = File.expand_path('..', __FILE__)
|
||||||
engine_dir = File.expand_path('engine', current_directory)
|
engine_dir = File.expand_path('engine', current_directory)
|
||||||
framework_name = 'Flutter.framework'
|
framework_name = 'Flutter.xcframework'
|
||||||
copied_engine = File.expand_path(framework_name, engine_dir)
|
copied_engine = File.expand_path(framework_name, engine_dir)
|
||||||
if !File.exist?(copied_engine)
|
if !File.exist?(copied_engine)
|
||||||
# Copy the debug engine to have something to link against if the xcode backend script has not run yet.
|
# Copy the debug engine to have something to link against if the xcode backend script has not run yet.
|
||||||
|
@ -42,9 +42,67 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('getArtifactPath', () {
|
testWithoutContext('getArtifactPath', () {
|
||||||
|
final String xcframeworkPath = artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterXcframework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: BuildMode.release),
|
xcframeworkPath,
|
||||||
fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.framework'),
|
fileSystem.path.join(
|
||||||
|
'root',
|
||||||
|
'bin',
|
||||||
|
'cache',
|
||||||
|
'artifacts',
|
||||||
|
'engine',
|
||||||
|
'ios-release',
|
||||||
|
'Flutter.xcframework',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
() => artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator,
|
||||||
|
),
|
||||||
|
throwsToolExit(
|
||||||
|
message:
|
||||||
|
'No xcframework found at $xcframeworkPath. Try running "flutter build ios".'),
|
||||||
|
);
|
||||||
|
fileSystem.directory(xcframeworkPath).createSync(recursive: true);
|
||||||
|
expect(
|
||||||
|
() => artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator,
|
||||||
|
),
|
||||||
|
throwsToolExit(message: 'No iOS frameworks found in $xcframeworkPath'),
|
||||||
|
);
|
||||||
|
|
||||||
|
fileSystem
|
||||||
|
.directory(xcframeworkPath)
|
||||||
|
.childDirectory('ios-x86_64-simulator')
|
||||||
|
.childDirectory('Flutter.framework')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
fileSystem
|
||||||
|
.directory(xcframeworkPath)
|
||||||
|
.childDirectory('ios-armv7_arm64')
|
||||||
|
.childDirectory('Flutter.framework')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
expect(
|
||||||
|
artifacts.getArtifactPath(Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator),
|
||||||
|
fileSystem.path
|
||||||
|
.join(xcframeworkPath, 'ios-x86_64-simulator', 'Flutter.framework'),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
artifacts.getArtifactPath(Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios, mode: BuildMode.release, environmentType: EnvironmentType.physical),
|
||||||
|
fileSystem.path.join(xcframeworkPath, 'ios-armv7_arm64', 'Flutter.framework'),
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release),
|
artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release),
|
||||||
@ -136,13 +194,78 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('getArtifactPath', () {
|
testWithoutContext('getArtifactPath', () {
|
||||||
expect(
|
final String xcframeworkPath = artifacts.getArtifactPath(
|
||||||
artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: BuildMode.release),
|
Artifact.flutterXcframework,
|
||||||
fileSystem.path.join('/out', 'android_debug_unopt', 'Flutter.framework'),
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release),
|
xcframeworkPath,
|
||||||
fileSystem.path.join('/out', 'android_debug_unopt', 'Flutter.xcframework'),
|
fileSystem.path
|
||||||
|
.join('/out', 'android_debug_unopt', 'Flutter.xcframework'),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
() => artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator,
|
||||||
|
),
|
||||||
|
throwsToolExit(
|
||||||
|
message:
|
||||||
|
'No xcframework found at /out/android_debug_unopt/Flutter.xcframework. Try running "flutter build ios".'),
|
||||||
|
);
|
||||||
|
fileSystem.directory(xcframeworkPath).createSync(recursive: true);
|
||||||
|
expect(
|
||||||
|
() => artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator,
|
||||||
|
),
|
||||||
|
throwsToolExit(
|
||||||
|
message:
|
||||||
|
'No iOS frameworks found in /out/android_debug_unopt/Flutter.xcframework'),
|
||||||
|
);
|
||||||
|
|
||||||
|
fileSystem
|
||||||
|
.directory(xcframeworkPath)
|
||||||
|
.childDirectory('ios-x86_64-simulator')
|
||||||
|
.childDirectory('Flutter.framework')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
fileSystem
|
||||||
|
.directory(xcframeworkPath)
|
||||||
|
.childDirectory('ios-armv7_arm64')
|
||||||
|
.childDirectory('Flutter.framework')
|
||||||
|
.createSync(recursive: true);
|
||||||
|
expect(
|
||||||
|
artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.simulator,
|
||||||
|
),
|
||||||
|
fileSystem.path
|
||||||
|
.join(xcframeworkPath, 'ios-x86_64-simulator', 'Flutter.framework'),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterFramework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
environmentType: EnvironmentType.physical,
|
||||||
|
),
|
||||||
|
fileSystem.path
|
||||||
|
.join(xcframeworkPath, 'ios-armv7_arm64', 'Flutter.framework'),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
artifacts.getArtifactPath(
|
||||||
|
Artifact.flutterXcframework,
|
||||||
|
platform: TargetPlatform.ios,
|
||||||
|
mode: BuildMode.release,
|
||||||
|
),
|
||||||
|
fileSystem.path
|
||||||
|
.join('/out', 'android_debug_unopt', 'Flutter.xcframework'),
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
artifacts.getArtifactPath(Artifact.flutterTester),
|
artifacts.getArtifactPath(Artifact.flutterTester),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user