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

Add XCFramework artifacts (#71113)

parent e2447247
......@@ -18,6 +18,7 @@ enum Artifact {
/// The flutter tester binary.
flutterTester,
flutterFramework,
flutterXcframework,
/// The framework directory of the macOS desktop.
flutterMacOSFramework,
vmSnapshotData,
......@@ -94,6 +95,8 @@ String _artifactToFileName(Artifact artifact, [ TargetPlatform platform, BuildMo
return 'flutter_tester$exe';
case Artifact.flutterFramework:
return 'Flutter.framework';
case Artifact.flutterXcframework:
return 'Flutter.xcframework';
case Artifact.flutterMacOSFramework:
return 'FlutterMacOS.framework';
case Artifact.vmSnapshotData:
......@@ -208,8 +211,13 @@ abstract class Artifacts {
);
}
// Returns the requested [artifact] for the [platform] and [mode] combination.
String getArtifactPath(Artifact artifact, { TargetPlatform platform, BuildMode mode });
/// Returns the requested [artifact] for the [platform], [mode], and [environmentType] combination.
String getArtifactPath(
Artifact artifact, {
TargetPlatform platform,
BuildMode mode,
EnvironmentType environmentType,
});
// Returns which set of engine artifacts is currently used for the [platform]
// and [mode] combination.
......@@ -235,7 +243,12 @@ class CachedArtifacts implements Artifacts {
final Cache _cache;
@override
String getArtifactPath(Artifact artifact, { TargetPlatform platform, BuildMode mode }) {
String getArtifactPath(
Artifact artifact, {
TargetPlatform platform,
BuildMode mode,
EnvironmentType environmentType,
}) {
switch (platform) {
case TargetPlatform.android_arm:
case TargetPlatform.android_arm64:
......@@ -243,7 +256,7 @@ class CachedArtifacts implements Artifacts {
case TargetPlatform.android_x86:
return _getAndroidArtifactPath(artifact, platform, mode);
case TargetPlatform.ios:
return _getIosArtifactPath(artifact, platform, mode);
return _getIosArtifactPath(artifact, platform, mode, environmentType);
case TargetPlatform.darwin_x64:
case TargetPlatform.linux_x64:
case TargetPlatform.windows_x64:
......@@ -288,10 +301,12 @@ class CachedArtifacts implements Artifacts {
}
}
String _getIosArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
String _getIosArtifactPath(Artifact artifact, TargetPlatform platform,
BuildMode mode, EnvironmentType environmentType) {
switch (artifact) {
case Artifact.genSnapshot:
case Artifact.flutterFramework:
case Artifact.flutterXcframework:
case Artifact.frontendServerSnapshotForEngineDartSdk:
final String artifactFileName = _artifactToFileName(artifact);
final String engineDir = _getEngineArtifactsPath(platform, mode);
......@@ -534,7 +549,12 @@ class LocalEngineArtifacts implements Artifacts {
final Platform _platform;
@override
String getArtifactPath(Artifact artifact, { TargetPlatform platform, BuildMode mode }) {
String getArtifactPath(
Artifact artifact, {
TargetPlatform platform,
BuildMode mode,
EnvironmentType environmentType,
}) {
platform ??= _currentHostPlatform(_platform);
final bool isDirectoryArtifact = artifact == Artifact.flutterWebSdk || artifact == Artifact.flutterPatchedSdkPath;
final String artifactFileName = isDirectoryArtifact ? null : _artifactToFileName(artifact, platform, mode);
......@@ -547,6 +567,8 @@ class LocalEngineArtifacts implements Artifacts {
case Artifact.vmSnapshotData:
return _fileSystem.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', artifactFileName);
case Artifact.icuData:
case Artifact.flutterXcframework:
case Artifact.flutterMacOSFramework:
return _fileSystem.path.join(engineOutPath, artifactFileName);
case Artifact.platformKernelDill:
if (platform == TargetPlatform.fuchsia_x64 || platform == TargetPlatform.fuchsia_arm64) {
......@@ -557,8 +579,6 @@ class LocalEngineArtifacts implements Artifacts {
return _fileSystem.path.join(_getFlutterPatchedSdkPath(mode), 'lib', artifactFileName);
case Artifact.flutterFramework:
return _fileSystem.path.join(engineOutPath, artifactFileName);
case Artifact.flutterMacOSFramework:
return _fileSystem.path.join(engineOutPath, artifactFileName);
case Artifact.flutterPatchedSdkPath:
// When using local engine always use [BuildMode.debug] regardless of
// what was specified in [mode] argument because local engine will
......@@ -712,7 +732,12 @@ class OverrideArtifacts implements Artifacts {
final File flutterPatchedSdk;
@override
String getArtifactPath(Artifact artifact, { TargetPlatform platform, BuildMode mode }) {
String getArtifactPath(
Artifact artifact, {
TargetPlatform platform,
BuildMode mode,
EnvironmentType environmentType,
}) {
if (artifact == Artifact.frontendServerSnapshotForEngineDartSdk && frontendServer != null) {
return frontendServer.path;
}
......@@ -725,7 +750,12 @@ class OverrideArtifacts implements Artifacts {
if (artifact == Artifact.flutterPatchedSdkPath && flutterPatchedSdk != null) {
return flutterPatchedSdk.path;
}
return parent.getArtifactPath(artifact, platform: platform, mode: mode);
return parent.getArtifactPath(
artifact,
platform: platform,
mode: mode,
environmentType: environmentType,
);
}
@override
......@@ -742,7 +772,12 @@ String _dartSdkPath(FileSystem fileSystem) {
class _TestArtifacts implements Artifacts {
@override
String getArtifactPath(Artifact artifact, {TargetPlatform platform, BuildMode mode}) {
String getArtifactPath(
Artifact artifact, {
TargetPlatform platform,
BuildMode mode,
EnvironmentType environmentType,
}) {
final StringBuffer buffer = StringBuffer();
buffer.write(artifact);
if (platform != null) {
......@@ -751,6 +786,9 @@ class _TestArtifacts implements Artifacts {
if (mode != null) {
buffer.write('.$mode');
}
if (environmentType != null) {
buffer.write('.$environmentType');
}
return buffer.toString();
}
......
......@@ -12,6 +12,7 @@ import '../../base/io.dart';
import '../../base/process.dart';
import '../../build_info.dart';
import '../../globals.dart' as globals hide fs, logger, processManager, artifacts;
import '../../macos/xcode.dart';
import '../../project.dart';
import '../build_system.dart';
import '../depfile.dart';
......@@ -267,10 +268,16 @@ abstract class UnpackIOS extends Target {
@override
Future<void> build(Environment environment) async {
if (environment.defines[kSdkRoot] == null) {
throw MissingDefineException(kSdkRoot, name);
}
final Directory sdkRoot = environment.fileSystem.directory(environment.defines[kSdkRoot]);
final EnvironmentType environmentType = environmentTypeFromSdkroot(sdkRoot);
final String basePath = environment.artifacts.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.ios,
mode: buildMode,
environmentType: environmentType,
);
final ProcessResult result = environment.processManager.runSync(<String>[
......
......@@ -459,7 +459,7 @@ end
// copy the corresponding engine.
// A plugin framework built with bitcode must link against the bitcode version
// of Flutter.framework (Release).
_project.ios.copyEngineArtifactToProject(mode);
_project.ios.copyEngineArtifactToProject(mode, EnvironmentType.physical);
final String bitcodeGenerationMode = mode == BuildMode.release ?
'bitcode' : 'marker'; // In release, force bitcode embedding without archiving.
......
......@@ -648,11 +648,11 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
ephemeralDirectory,
);
}
copyEngineArtifactToProject(BuildMode.debug);
copyEngineArtifactToProject(BuildMode.debug, EnvironmentType.physical);
}
}
void copyEngineArtifactToProject(BuildMode mode) {
void copyEngineArtifactToProject(BuildMode mode, EnvironmentType environmentType) {
// Copy framework from engine cache. The actual build mode
// doesn't actually matter as it will be overwritten by xcode_backend.sh.
// However, cocoapods will run before that script and requires something
......@@ -662,6 +662,7 @@ class IosProject extends FlutterProjectPlatform implements XcodeBasedProject {
Artifact.flutterFramework,
platform: TargetPlatform.ios,
mode: mode,
environmentType: environmentType,
)
);
if (framework.existsSync()) {
......
......@@ -544,8 +544,12 @@ include ':app'
String expectedBuildName,
String expectedBuildNumber,
}) async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.android_arm, mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.android_arm,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(globals.fs.path.join('out', 'android_arm'));
final File manifestFile = globals.fs.file('path/to/project/pubspec.yaml');
......@@ -1686,8 +1690,12 @@ plugin1=${plugin1.path}
});
testUsingContext('build apk uses selected local engine,the engine abi is arm', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.android_arm, mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.android_arm,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_arm'));
fileSystem.file('out/android_arm/flutter_embedding_release.pom')
......@@ -1779,8 +1787,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build apk uses selected local engine,the engine abi is arm64', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_arm64'));
fileSystem.file('out/android_arm64/flutter_embedding_release.pom')
......@@ -1872,8 +1884,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build apk uses selected local engine,the engine abi is x86', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_x86'));
fileSystem.file('out/android_x86/flutter_embedding_release.pom')
......@@ -1965,8 +1981,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build apk uses selected local engine,the engine abi is x64', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_x64'));
fileSystem.file('out/android_x64/flutter_embedding_release.pom')
......@@ -2110,8 +2130,12 @@ plugin1=${plugin1.path}
});
testUsingContext('build aar uses selected local engine,the engine abi is arm', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.android_arm, mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: TargetPlatform.android_arm,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_arm'));
fileSystem.file('out/android_arm/flutter_embedding_release.pom')
......@@ -2207,8 +2231,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build aar uses selected local engine,the engine abi is arm64', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_arm64'));
fileSystem.file('out/android_arm64/flutter_embedding_release.pom')
......@@ -2305,8 +2333,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build aar uses selected local engine,the engine abi is x86', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_x86'));
fileSystem.file('out/android_x86/flutter_embedding_release.pom')
......@@ -2403,8 +2435,12 @@ plugin1=${plugin1.path}
testUsingContext(
'build aar uses selected local engine,the engine abi is x64', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: anyNamed('platform'), mode: anyNamed('mode'))).thenReturn('engine');
when(mockArtifacts.getArtifactPath(
Artifact.flutterFramework,
platform: anyNamed('platform'),
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType'),
)).thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fileSystem.path.join('out', 'android_x64'));
fileSystem.file('out/android_x64/flutter_embedding_release.pom')
......
......@@ -46,6 +46,10 @@ void main() {
artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: BuildMode.release),
fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.framework'),
);
expect(
artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release),
fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.xcframework'),
);
expect(
artifacts.getArtifactPath(Artifact.flutterTester),
fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'linux-x64', 'flutter_tester'),
......@@ -136,6 +140,10 @@ void main() {
artifacts.getArtifactPath(Artifact.flutterFramework, platform: TargetPlatform.ios, mode: BuildMode.release),
fileSystem.path.join('/out', 'android_debug_unopt', 'Flutter.framework'),
);
expect(
artifacts.getArtifactPath(Artifact.flutterXcframework, platform: TargetPlatform.ios, mode: BuildMode.release),
fileSystem.path.join('/out', 'android_debug_unopt', 'Flutter.xcframework'),
);
expect(
artifacts.getArtifactPath(Artifact.flutterTester),
fileSystem.path.join('/out', 'android_debug_unopt', 'flutter_tester'),
......
......@@ -238,30 +238,65 @@ void main() {
Platform: () => macPlatform,
});
testWithoutContext('Unpack copies Flutter.framework', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory outputDir = fileSystem.directory('output');
final Environment environment = Environment.test(
fileSystem.currentDirectory,
processManager: processManager,
artifacts: artifacts,
logger: logger,
fileSystem: fileSystem,
outputDir: outputDir,
);
group('copy engine Flutter.framework', () {
testWithoutContext('iphonesimulator', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory outputDir = fileSystem.directory('output');
final Environment environment = Environment.test(
fileSystem.currentDirectory,
processManager: processManager,
artifacts: artifacts,
logger: logger,
fileSystem: fileSystem,
outputDir: outputDir,
defines: <String, String>{
kSdkRoot: 'path/to/iPhoneSimulator.sdk',
},
);
processManager.addCommand(
FakeCommand(command: <String>[
'rsync',
'-av',
'--delete',
'--filter',
'- .DS_Store/',
'Artifact.flutterFramework.TargetPlatform.ios.debug',
outputDir.path,
]),
);
processManager.addCommand(
FakeCommand(command: <String>[
'rsync',
'-av',
'--delete',
'--filter',
'- .DS_Store/',
'Artifact.flutterFramework.TargetPlatform.ios.debug.EnvironmentType.simulator',
outputDir.path,
]),
);
await const DebugUnpackIOS().build(environment);
});
testWithoutContext('iphoneos', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final Directory outputDir = fileSystem.directory('output');
final Environment environment = Environment.test(
fileSystem.currentDirectory,
processManager: processManager,
artifacts: artifacts,
logger: logger,
fileSystem: fileSystem,
outputDir: outputDir,
defines: <String, String>{
kSdkRoot: 'path/to/iPhoneOS.sdk',
},
);
processManager.addCommand(
FakeCommand(command: <String>[
'rsync',
'-av',
'--delete',
'--filter',
'- .DS_Store/',
'Artifact.flutterFramework.TargetPlatform.ios.debug.EnvironmentType.physical',
outputDir.path,
]),
);
await const DebugUnpackIOS().build(environment);
await const DebugUnpackIOS().build(environment);
});
});
}
......@@ -638,7 +638,10 @@ Information about project "Runner":
testUsingOsxContext('sets OTHER_LDFLAGS for iOS', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn(fs.path.join('engine', 'Flutter.framework'));
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn(fs.path.join('engine', 'Flutter.framework'));
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
......@@ -663,7 +666,10 @@ Information about project "Runner":
testUsingOsxContext('do not set OTHER_LDFLAGS for macOS', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterMacOSFramework,
platform: TargetPlatform.darwin_x64, mode: anyNamed('mode'))).thenReturn(fs.path.join('engine', 'FlutterMacOS.framework'));
platform: TargetPlatform.darwin_x64,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn(fs.path.join('engine', 'FlutterMacOS.framework'));
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
......@@ -689,7 +695,10 @@ Information about project "Runner":
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
......@@ -714,7 +723,10 @@ Information about project "Runner":
testUsingOsxContext('sets TRACK_WIDGET_CREATION=true when trackWidgetCreation is true', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, trackWidgetCreation: true, treeShakeIcons: false);
final FlutterProject project = FlutterProject.fromPath('path/to/project');
......@@ -738,7 +750,10 @@ Information about project "Runner":
testUsingOsxContext('does not set TRACK_WIDGET_CREATION when trackWidgetCreation is false', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
final FlutterProject project = FlutterProject.fromPath('path/to/project');
......@@ -762,7 +777,10 @@ Information about project "Runner":
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile'));
const BuildInfo buildInfo = BuildInfo(BuildMode.debug, null, treeShakeIcons: false);
......@@ -795,7 +813,10 @@ Information about project "Runner":
String expectedBuildNumber,
}) async {
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework,
platform: TargetPlatform.ios, mode: anyNamed('mode'))).thenReturn('engine');
platform: TargetPlatform.ios,
mode: anyNamed('mode'),
environmentType: anyNamed('environmentType')))
.thenReturn('engine');
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios'));
final File manifestFile = fs.file('path/to/project/pubspec.yaml');
......
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