Revert "[flutter_tools] split project parsing/validation into separate function (#64814)" (#65202)

This reverts commit 8eed690442.
This commit is contained in:
Jonah Williams 2020-09-03 14:25:29 -07:00 committed by GitHub
parent 8eed690442
commit 30a0b5a50c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 150 additions and 179 deletions

View file

@ -318,14 +318,14 @@ class IOSDevice extends Device {
// TODO(chinmaygarde): Use mainPath, route. // TODO(chinmaygarde): Use mainPath, route.
_logger.printTrace('Building ${package.name} for $id'); _logger.printTrace('Building ${package.name} for $id');
// Step 1: Build the precompiled application if necessary. // Step 1: Build the precompiled/DBC application if necessary.
final XcodeBuildResult buildResult = await buildXcodeProject( final XcodeBuildResult buildResult = await buildXcodeProject(
app: package as BuildableIOSApp, app: package as BuildableIOSApp,
buildInfo: debuggingOptions.buildInfo, buildInfo: debuggingOptions.buildInfo,
targetOverride: mainPath, targetOverride: mainPath,
buildForDevice: true, buildForDevice: true,
activeArch: cpuArchitecture, activeArch: cpuArchitecture,
deviceID: id, deviceID: id,
); );
if (!buildResult.success) { if (!buildResult.success) {
_logger.printError('Could not build the precompiled application for the device.'); _logger.printError('Could not build the precompiled application for the device.');

View file

@ -89,17 +89,20 @@ class IMobileDevice {
} }
} }
Future<ParsedProjectInfo> _valdateXcodeBuild({ Future<XcodeBuildResult> buildXcodeProject({
@required BuildableIOSApp app, BuildableIOSApp app,
@required BuildInfo buildInfo, BuildInfo buildInfo,
@required bool codesign, String targetOverride,
@required bool buildForDevice, bool buildForDevice,
@required String targetOverride, DarwinArch activeArch,
@required String deviceID, bool codesign = true,
String deviceID,
bool configOnly = false,
}) async { }) async {
if (!upgradePbxProjWithFlutterAssets(app.project, globals.logger)) { if (!upgradePbxProjWithFlutterAssets(app.project, globals.logger)) {
return null; return XcodeBuildResult(success: false);
} }
final List<IOSMigrator> migrators = <IOSMigrator>[ final List<IOSMigrator> migrators = <IOSMigrator>[
RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.xcode, globals.flutterUsage), RemoveFrameworkLinkAndEmbeddingMigration(app.project, globals.logger, globals.xcode, globals.flutterUsage),
XcodeBuildSystemMigration(app.project, globals.logger), XcodeBuildSystemMigration(app.project, globals.logger),
@ -108,12 +111,13 @@ Future<ParsedProjectInfo> _valdateXcodeBuild({
final IOSMigration migration = IOSMigration(migrators); final IOSMigration migration = IOSMigration(migrators);
if (!migration.run()) { if (!migration.run()) {
return null; return XcodeBuildResult(success: false);
} }
if (!_checkXcodeVersion()) { if (!_checkXcodeVersion()) {
return null; return XcodeBuildResult(success: false);
} }
await removeFinderExtendedAttributes(app.project.hostAppRoot, processUtils, globals.logger); await removeFinderExtendedAttributes(app.project.hostAppRoot, processUtils, globals.logger);
final XcodeProjectInfo projectInfo = await app.project.projectInfo(); final XcodeProjectInfo projectInfo = await app.project.projectInfo();
@ -145,7 +149,7 @@ Future<ParsedProjectInfo> _valdateXcodeBuild({
globals.printError(' in the .xcconfig file for that configuration and run from Xcode.'); globals.printError(' in the .xcconfig file for that configuration and run from Xcode.');
globals.printError(''); globals.printError('');
globals.printError('4. If you are not using completely custom build configurations, name the newly created configuration ${buildInfo.modeName}.'); globals.printError('4. If you are not using completely custom build configurations, name the newly created configuration ${buildInfo.modeName}.');
return null; return XcodeBuildResult(success: false);
} }
final FlutterManifest manifest = app.project.parent.manifest; final FlutterManifest manifest = app.project.parent.manifest;
@ -163,24 +167,8 @@ Future<ParsedProjectInfo> _valdateXcodeBuild({
globals.printStatus('Warning: Missing build number (CFBundleVersion).'); globals.printStatus('Warning: Missing build number (CFBundleVersion).');
} }
if (buildNameIsMissing || buildNumberIsMissing) { if (buildNameIsMissing || buildNumberIsMissing) {
globals.printError( globals.printError('Action Required: You must set a build name and number in the pubspec.yaml '
'Action Required: You must set a build name and number in the pubspec.yaml ' 'file version field before submitting to the App Store.');
'file version field before submitting to the App Store.'
);
}
// Check if the project contains a watchOS companion app.
final bool hasWatchCompanion = await app.project.containsWatchCompanion(
projectInfo.targets,
buildInfo,
);
if (hasWatchCompanion) {
globals.printStatus('Watch companion app found. Adjusting build settings.');
if (!buildForDevice && (deviceID == null || deviceID.isEmpty)) {
globals.printError('No simulator device ID has been set.');
globals.printError('A device ID is required to build an app with a watchOS companion app.');
globals.printError('Please run "flutter devices" to get a list of available device IDs');
globals.printError('and specify one using the -d, --device-id flag.');
}
} }
Map<String, String> autoSigningConfigs; Map<String, String> autoSigningConfigs;
@ -193,14 +181,6 @@ Future<ParsedProjectInfo> _valdateXcodeBuild({
); );
} }
String workspace;
for (final FileSystemEntity entity in app.project.hostAppRoot.listSync()) {
if (globals.fs.path.extension(entity.path) == '.xcworkspace') {
workspace = globals.fs.path.basename(entity.path);
break;
}
}
final FlutterProject project = FlutterProject.current(); final FlutterProject project = FlutterProject.current();
await updateGeneratedXcodeProperties( await updateGeneratedXcodeProperties(
project: project, project: project,
@ -208,94 +188,94 @@ Future<ParsedProjectInfo> _valdateXcodeBuild({
buildInfo: buildInfo, buildInfo: buildInfo,
); );
await processPodsIfNeeded(project.ios, getIosBuildDirectory(), buildInfo.mode); await processPodsIfNeeded(project.ios, getIosBuildDirectory(), buildInfo.mode);
return ParsedProjectInfo(
autoSigningConfigs: autoSigningConfigs,
projectInfo: projectInfo,
scheme: scheme,
configuration:configuration,
hasWatchCompanion: hasWatchCompanion,
workspace: workspace,
);
}
Future<XcodeBuildResult> buildXcodeProject({
@required BuildableIOSApp app,
@required BuildInfo buildInfo,
String targetOverride,
bool buildForDevice,
DarwinArch activeArch,
bool codesign = true,
String deviceID,
bool configOnly = false,
}) async {
final ParsedProjectInfo parsedProjectInfo = await _valdateXcodeBuild(
app: app,
buildInfo: buildInfo,
codesign: codesign,
buildForDevice: buildForDevice,
targetOverride: targetOverride,
deviceID: deviceID,
);
if (parsedProjectInfo == null) {
return XcodeBuildResult(success: false);
}
if (configOnly) { if (configOnly) {
return XcodeBuildResult(success: true); return XcodeBuildResult(success: true);
} }
final List<String> buildCommands = <String>[ final List<String> buildCommands = <String>[
'/usr/bin/env', '/usr/bin/env',
'xcrun', 'xcrun',
'xcodebuild', 'xcodebuild',
'-configuration', parsedProjectInfo.configuration, '-configuration', configuration,
];
if (globals.logger.isVerbose) {
// An environment variable to be passed to xcode_backend.sh determining // An environment variable to be passed to xcode_backend.sh determining
// whether to echo back executed commands. // whether to echo back executed commands.
if (globals.logger.isVerbose) buildCommands.add('VERBOSE_SCRIPT_LOGGING=YES');
'VERBOSE_SCRIPT_LOGGING=YES' } else {
else // This will print warnings and errors only.
// This will print warnings and errors only. buildCommands.add('-quiet');
'-quiet', }
if (parsedProjectInfo.autoSigningConfigs != null)
...<String>[ if (autoSigningConfigs != null) {
for (final MapEntry<String, String> signingConfig in parsedProjectInfo.autoSigningConfigs.entries) for (final MapEntry<String, String> signingConfig in autoSigningConfigs.entries) {
'${signingConfig.key}=${signingConfig.value}' buildCommands.add('${signingConfig.key}=${signingConfig.value}');
'-allowProvisioningUpdates', }
'-allowProvisioningDeviceRegistration', buildCommands.add('-allowProvisioningUpdates');
], buildCommands.add('-allowProvisioningDeviceRegistration');
if (!codesign) }
...<String>[
final List<FileSystemEntity> contents = app.project.hostAppRoot.listSync();
for (final FileSystemEntity entity in contents) {
if (globals.fs.path.extension(entity.path) == '.xcworkspace') {
buildCommands.addAll(<String>[
'-workspace', globals.fs.path.basename(entity.path),
'-scheme', scheme,
'BUILD_DIR=${globals.fs.path.absolute(getIosBuildDirectory())}',
]);
break;
}
}
// Check if the project contains a watchOS companion app.
final bool hasWatchCompanion = await app.project.containsWatchCompanion(
projectInfo.targets,
buildInfo,
);
if (hasWatchCompanion) {
// The -sdk argument has to be omitted if a watchOS companion app exists.
// Otherwise the build will fail as WatchKit dependencies cannot be build using the iOS SDK.
globals.printStatus('Watch companion app found. Adjusting build settings.');
if (!buildForDevice && (deviceID == null || deviceID == '')) {
globals.printError('No simulator device ID has been set.');
globals.printError('A device ID is required to build an app with a watchOS companion app.');
globals.printError('Please run "flutter devices" to get a list of available device IDs');
globals.printError('and specify one using the -d, --device-id flag.');
return XcodeBuildResult(success: false);
}
if (!buildForDevice) {
buildCommands.addAll(<String>['-destination', 'id=$deviceID']);
}
} else {
if (buildForDevice) {
buildCommands.addAll(<String>['-sdk', 'iphoneos']);
} else {
buildCommands.addAll(<String>['-sdk', 'iphonesimulator', '-arch', 'x86_64']);
}
}
if (activeArch != null) {
final String activeArchName = getNameForDarwinArch(activeArch);
if (activeArchName != null) {
buildCommands.add('ONLY_ACTIVE_ARCH=YES');
// Setting ARCHS to $activeArchName will break the build if a watchOS companion app exists,
// as it cannot be build for the architecture of the flutter app.
if (!hasWatchCompanion) {
buildCommands.add('ARCHS=$activeArchName');
}
}
}
if (!codesign) {
buildCommands.addAll(
<String>[
'CODE_SIGNING_ALLOWED=NO', 'CODE_SIGNING_ALLOWED=NO',
'CODE_SIGNING_REQUIRED=NO', 'CODE_SIGNING_REQUIRED=NO',
'CODE_SIGNING_IDENTITY=""', 'CODE_SIGNING_IDENTITY=""',
], ],
// The -sdk argument has to be omitted if a watchOS companion app exists. );
// Otherwise the build will fail as WatchKit dependencies cannot be build using the iOS SDK. }
if (parsedProjectInfo.hasWatchCompanion && !buildForDevice)
...<String>['-destination', 'id=$deviceID']
else if (buildForDevice)
...<String>['-sdk', 'iphoneos']
else
...<String>['-sdk', 'iphonesimulator', '-arch', 'x86_64'],
if (parsedProjectInfo.workspace != null)
...<String>[
'-workspace', parsedProjectInfo.workspace,
'-scheme', parsedProjectInfo.scheme,
'BUILD_DIR=${globals.fs.path.absolute(getIosBuildDirectory())}',
],
if (activeArch != null)
'ONLY_ACTIVE_ARCH=YES',
// Setting ARCHS to $activeArchName will break the build if a watchOS companion app exists,
// as it cannot be build for the architecture of the flutter app.
if (activeArch != null && !parsedProjectInfo.hasWatchCompanion)
'ARCHS=${getNameForDarwinArch(activeArch)}',
/// Disable code indexing when running from the CLI to improve overall performance
'COMPILER_INDEX_STORE_ENABLE=NO',
...environmentVariablesAsXcodeBuildSettings(globals.platform),
];
Status buildSubStatus; Status buildSubStatus;
Status initialBuildStatus; Status initialBuildStatus;
@ -337,6 +317,12 @@ Future<XcodeBuildResult> buildXcodeProject({
buildCommands.add('SCRIPT_OUTPUT_STREAM_FILE=${scriptOutputPipeFile.absolute.path}'); buildCommands.add('SCRIPT_OUTPUT_STREAM_FILE=${scriptOutputPipeFile.absolute.path}');
} }
// Don't log analytics for downstream Flutter commands.
// e.g. `flutter build bundle`.
buildCommands.add('FLUTTER_SUPPRESS_ANALYTICS=true');
buildCommands.add('COMPILER_INDEX_STORE_ENABLE=NO');
buildCommands.addAll(environmentVariablesAsXcodeBuildSettings(globals.platform));
final Stopwatch sw = Stopwatch()..start(); final Stopwatch sw = Stopwatch()..start();
initialBuildStatus = globals.logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.slowOperation); initialBuildStatus = globals.logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.slowOperation);
@ -413,47 +399,49 @@ Future<XcodeBuildResult> buildXcodeProject({
buildSettings: buildSettings, buildSettings: buildSettings,
), ),
); );
}
// If the app contains a watch companion target, the sdk argument of xcodebuild has to be omitted.
// For some reason this leads to TARGET_BUILD_DIR always ending in 'iphoneos' even though the
// actual directory will end with 'iphonesimulator' for simulator builds.
// The value of TARGET_BUILD_DIR is adjusted to accommodate for this effect.
String targetBuildDir = buildSettings['TARGET_BUILD_DIR'];
if (parsedProjectInfo.hasWatchCompanion && !buildForDevice) {
globals.printTrace('Replacing iphoneos with iphonesimulator in TARGET_BUILD_DIR.');
targetBuildDir = targetBuildDir.replaceFirst('iphoneos', 'iphonesimulator');
}
final String expectedOutputDirectory = globals.fs.path.join(
targetBuildDir,
buildSettings['WRAPPER_NAME'],
);
String outputDir;
if (globals.fs.isDirectorySync(expectedOutputDirectory)) {
// Copy app folder to a place where other tools can find it without knowing
// the BuildInfo.
outputDir = expectedOutputDirectory.replaceFirst('/${parsedProjectInfo.configuration}-', '/');
if (globals.fs.isDirectorySync(outputDir)) {
// Previous output directory might have incompatible artifacts
// (for example, kernel binary files produced from previous run).
globals.fs.directory(outputDir).deleteSync(recursive: true);
}
globals.fsUtils.copyDirectorySync(
globals.fs.directory(expectedOutputDirectory),
globals.fs.directory(outputDir),
);
} else { } else {
globals.printError('Build succeeded but the expected app at $expectedOutputDirectory not found'); // If the app contains a watch companion target, the sdk argument of xcodebuild has to be omitted.
// For some reason this leads to TARGET_BUILD_DIR always ending in 'iphoneos' even though the
// actual directory will end with 'iphonesimulator' for simulator builds.
// The value of TARGET_BUILD_DIR is adjusted to accommodate for this effect.
String targetBuildDir = buildSettings['TARGET_BUILD_DIR'];
if (hasWatchCompanion && !buildForDevice) {
globals.printTrace('Replacing iphoneos with iphonesimulator in TARGET_BUILD_DIR.');
targetBuildDir = targetBuildDir.replaceFirst('iphoneos', 'iphonesimulator');
}
final String expectedOutputDirectory = globals.fs.path.join(
targetBuildDir,
buildSettings['WRAPPER_NAME'],
);
String outputDir;
if (globals.fs.isDirectorySync(expectedOutputDirectory)) {
// Copy app folder to a place where other tools can find it without knowing
// the BuildInfo.
outputDir = expectedOutputDirectory.replaceFirst('/$configuration-', '/');
if (globals.fs.isDirectorySync(outputDir)) {
// Previous output directory might have incompatible artifacts
// (for example, kernel binary files produced from previous run).
globals.fs.directory(outputDir).deleteSync(recursive: true);
}
globals.fsUtils.copyDirectorySync(
globals.fs.directory(expectedOutputDirectory),
globals.fs.directory(outputDir),
);
} else {
globals.printError('Build succeeded but the expected app at $expectedOutputDirectory not found');
}
return XcodeBuildResult(
success: true,
output: outputDir,
xcodeBuildExecution: XcodeBuildExecution(
buildCommands: buildCommands,
appDirectory: app.project.hostAppRoot.path,
buildForPhysicalDevice: buildForDevice,
buildSettings: buildSettings,
),
);
} }
return XcodeBuildResult(
success: true,
output: outputDir,
xcodeBuildExecution: XcodeBuildExecution(
buildCommands: buildCommands,
appDirectory: app.project.hostAppRoot.path,
buildForPhysicalDevice: buildForDevice,
buildSettings: buildSettings,
));
} }
/// Extended attributes applied by Finder can cause code signing errors. Remove them. /// Extended attributes applied by Finder can cause code signing errors. Remove them.
@ -656,21 +644,3 @@ bool upgradePbxProjWithFlutterAssets(IosProject project, Logger logger) {
xcodeProjectFile.writeAsStringSync(buffer.toString()); xcodeProjectFile.writeAsStringSync(buffer.toString());
return true; return true;
} }
class ParsedProjectInfo {
const ParsedProjectInfo({
@required this.autoSigningConfigs,
@required this.projectInfo,
@required this.scheme,
@required this.configuration,
@required this.hasWatchCompanion,
@required this.workspace,
});
final Map<String, String> autoSigningConfigs;
final XcodeProjectInfo projectInfo;
final String scheme;
final String configuration;
final bool hasWatchCompanion;
final String workspace;
}

View file

@ -43,16 +43,17 @@ const List<String> kRunReleaseArgs = <String>[
'-configuration', '-configuration',
'Release', 'Release',
'-quiet', '-quiet',
'-sdk',
'iphoneos',
'-workspace', '-workspace',
'Runner.xcworkspace', 'Runner.xcworkspace',
'-scheme', '-scheme',
'Runner', 'Runner',
'BUILD_DIR=/build/ios', 'BUILD_DIR=/build/ios',
'-sdk',
'iphoneos',
'ONLY_ACTIVE_ARCH=YES', 'ONLY_ACTIVE_ARCH=YES',
'ARCHS=arm64', 'ARCHS=arm64',
'COMPILER_INDEX_STORE_ENABLE=NO' 'FLUTTER_SUPPRESS_ANALYTICS=true',
'COMPILER_INDEX_STORE_ENABLE=NO',
]; ];
const String kConcurrentBuildErrorMessage = ''' const String kConcurrentBuildErrorMessage = '''