mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
add version to pubspec.yaml (#16857)
Uses the `version` property from the `pubspec.yaml` file to set the corresponding fields in the `local.properties` file respectively in the `Generated.xcconfig` file. The `--build-name` and `--build-number` options have changed. Now they trump the `version` property from the `pubspec.yaml` file. If the `version` property is not set and the `--build-name` and `--build-number` options are not provided, the build command will not change the `local.properties` / `Generated.xcconfig` file.
This commit is contained in:
parent
f986048094
commit
c65e9d19a4
@ -3,9 +3,6 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../android/android_sdk.dart';
|
||||
import '../artifacts.dart';
|
||||
@ -17,7 +14,9 @@ import '../base/platform.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../bundle.dart' as bundle;
|
||||
import '../cache.dart';
|
||||
import '../flutter_manifest.dart';
|
||||
import '../globals.dart';
|
||||
import 'android_sdk.dart';
|
||||
import 'android_studio.dart';
|
||||
@ -95,7 +94,7 @@ Future<GradleProject> _gradleProject() async {
|
||||
// of calculating the app properties using Gradle. This may take minutes.
|
||||
Future<GradleProject> _readGradleProject() async {
|
||||
final String gradle = await _ensureGradle();
|
||||
updateLocalProperties();
|
||||
await updateLocalProperties();
|
||||
try {
|
||||
final Status status = logger.startProgress('Resolving dependencies...', expectSlowOperation: true);
|
||||
final RunResult runResult = await runCheckedAsync(
|
||||
@ -198,10 +197,13 @@ distributionUrl=https\\://services.gradle.org/distributions/gradle-$gradleVersio
|
||||
}
|
||||
|
||||
/// Create android/local.properties if needed, and update Flutter settings.
|
||||
void updateLocalProperties({String projectPath, BuildInfo buildInfo}) {
|
||||
Future<void> updateLocalProperties({String projectPath, BuildInfo buildInfo}) async {
|
||||
final File localProperties = (projectPath == null)
|
||||
? fs.file(fs.path.join('android', 'local.properties'))
|
||||
: fs.file(fs.path.join(projectPath, 'android', 'local.properties'));
|
||||
final String flutterManifest = (projectPath == null)
|
||||
? fs.path.join(bundle.defaultManifestPath)
|
||||
: fs.path.join(projectPath, bundle.defaultManifestPath);
|
||||
bool changed = false;
|
||||
|
||||
SettingsFile settings;
|
||||
@ -225,85 +227,39 @@ void updateLocalProperties({String projectPath, BuildInfo buildInfo}) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
FlutterManifest manifest;
|
||||
try {
|
||||
manifest = await FlutterManifest.createFromPath(flutterManifest);
|
||||
} catch (error) {
|
||||
throwToolExit('Failed to load pubspec.yaml: $error');
|
||||
}
|
||||
|
||||
final String buildName = buildInfo?.buildName ?? manifest.buildName;
|
||||
if (buildName != null) {
|
||||
settings.values['flutter.versionName'] = buildName;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
final int buildNumber = buildInfo?.buildNumber ?? manifest.buildNumber;
|
||||
if (buildNumber != null) {
|
||||
settings.values['flutter.versionCode'] = '$buildNumber';
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
settings.writeContents(localProperties);
|
||||
}
|
||||
|
||||
Future<Null> findAndReplaceVersionProperties({@required BuildInfo buildInfo}) {
|
||||
assert(buildInfo != null, 'buildInfo can\'t be null');
|
||||
final Completer<Null> completer = new Completer<Null>();
|
||||
|
||||
// early return, if nothing has to be changed
|
||||
if (buildInfo.buildNumber == null && buildInfo.buildName == null) {
|
||||
completer.complete();
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
final File appGradle = fs.file(fs.path.join('android', 'app', 'build.gradle'));
|
||||
final File appGradleTmp = fs.file(fs.path.join('android', 'app', 'build.gradle.tmp'));
|
||||
appGradleTmp.createSync();
|
||||
|
||||
if (appGradle.existsSync() && appGradleTmp.existsSync()) {
|
||||
final Stream<List<int>> inputStream = appGradle.openRead();
|
||||
final IOSink sink = appGradleTmp.openWrite();
|
||||
|
||||
inputStream.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
.map((String line) {
|
||||
|
||||
// find and replace build number
|
||||
if (buildInfo.buildNumber != null) {
|
||||
if (line.contains(new RegExp(r'^[ |\t]*(versionCode)[ =\t]*\d*'))) {
|
||||
return line.splitMapJoin(new RegExp(r'(versionCode)[ =\t]*\d*'), onMatch: (Match m) {
|
||||
return 'versionCode ${buildInfo.buildNumber}';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// find and replace build name
|
||||
if (buildInfo.buildName != null) {
|
||||
if (line.contains(new RegExp(r'^[ |\t]*(versionName)[ =\t]*\"[0-9.]*"'))) {
|
||||
return line.splitMapJoin(new RegExp(r'(versionName)[ =\t]*\"[0-9.]*"'), onMatch: (Match m) {
|
||||
return 'versionName "${buildInfo.buildName}"';
|
||||
});
|
||||
}
|
||||
}
|
||||
return line;
|
||||
})
|
||||
.listen((String line) {
|
||||
sink.writeln(line);
|
||||
},
|
||||
onDone: () {
|
||||
sink.close();
|
||||
try {
|
||||
final File gradleOld = appGradle.renameSync(fs.path.join('android', 'app', 'build.gradle.old'));
|
||||
appGradleTmp.renameSync(fs.path.join('android', 'app', 'build.gradle'));
|
||||
gradleOld.deleteSync();
|
||||
completer.complete();
|
||||
} catch (error) {
|
||||
printError('Failed to change version properties. $error');
|
||||
completer.completeError('Failed to change version properties. $error');
|
||||
}
|
||||
},
|
||||
onError: (dynamic error, StackTrace stack) {
|
||||
printError('Failed to change version properties. ${error.toString()}');
|
||||
sink.close();
|
||||
appGradleTmp.deleteSync();
|
||||
completer.completeError('Failed to change version properties. ${error.toString()}', stack);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
Future<Null> buildGradleProject(BuildInfo buildInfo, String target) async {
|
||||
// Update the local.properties file with the build mode.
|
||||
// Update the local.properties file with the build mode, version name and code.
|
||||
// FlutterPlugin v1 reads local.properties to determine build mode. Plugin v2
|
||||
// uses the standard Android way to determine what to build, but we still
|
||||
// update local.properties, in case we want to use it in the future.
|
||||
updateLocalProperties(buildInfo: buildInfo);
|
||||
await findAndReplaceVersionProperties(buildInfo: buildInfo);
|
||||
// Version name and number are provided by the pubspec.yaml file
|
||||
// and can be overwritten with flutter build command.
|
||||
// The default Gradle script reads the version name and number
|
||||
// from the local.properties file.
|
||||
await updateLocalProperties(buildInfo: buildInfo);
|
||||
|
||||
final String gradle = await _ensureGradle();
|
||||
|
||||
|
@ -289,11 +289,11 @@ To edit platform code in an IDE see https://flutter.io/platform-plugins/#edit-co
|
||||
|
||||
if (argResults['pub']) {
|
||||
await pubGet(context: PubContext.create, directory: appPath, offline: argResults['offline']);
|
||||
new FlutterProject(fs.directory(appPath)).ensureReadyForPlatformSpecificTooling();
|
||||
await new FlutterProject(fs.directory(appPath)).ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
|
||||
if (android_sdk.androidSdk != null)
|
||||
gradle.updateLocalProperties(projectPath: appPath);
|
||||
await gradle.updateLocalProperties(projectPath: appPath);
|
||||
|
||||
return generatedCount;
|
||||
}
|
||||
|
@ -82,13 +82,13 @@ class PackagesGetCommand extends FlutterCommand {
|
||||
|
||||
await _runPubGet(target);
|
||||
final FlutterProject rootProject = new FlutterProject(fs.directory(target));
|
||||
rootProject.ensureReadyForPlatformSpecificTooling();
|
||||
await rootProject.ensureReadyForPlatformSpecificTooling();
|
||||
|
||||
// Get/upgrade packages in example app as well
|
||||
if (rootProject.hasExampleApp) {
|
||||
final FlutterProject exampleProject = rootProject.example;
|
||||
await _runPubGet(exampleProject.directory.path);
|
||||
exampleProject.ensureReadyForPlatformSpecificTooling();
|
||||
await exampleProject.ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ import 'base/file_system.dart';
|
||||
import 'cache.dart';
|
||||
import 'globals.dart';
|
||||
|
||||
final RegExp _versionPattern = new RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?(\+(\d+))?$');
|
||||
|
||||
/// A wrapper around the `flutter` section in the `pubspec.yaml` file.
|
||||
class FlutterManifest {
|
||||
FlutterManifest._();
|
||||
@ -51,6 +53,36 @@ class FlutterManifest {
|
||||
|
||||
String get appName => _descriptor['name'] ?? '';
|
||||
|
||||
/// The version String from the `pubspec.yaml` file.
|
||||
/// Can be null if it isn't set or has a wrong format.
|
||||
String get appVersion {
|
||||
final String version = _descriptor['version']?.toString();
|
||||
if (version != null && _versionPattern.hasMatch(version))
|
||||
return version;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// The build version name from the `pubspec.yaml` file.
|
||||
/// Can be null if version isn't set or has a wrong format.
|
||||
String get buildName {
|
||||
if (appVersion != null && appVersion.contains('+'))
|
||||
return appVersion.split('+')?.elementAt(0);
|
||||
else
|
||||
return appVersion;
|
||||
}
|
||||
|
||||
/// The build version number from the `pubspec.yaml` file.
|
||||
/// Can be null if version isn't set or has a wrong format.
|
||||
int get buildNumber {
|
||||
if (appVersion != null && appVersion.contains('+')) {
|
||||
final String value = appVersion.split('+')?.elementAt(1);
|
||||
return value == null ? null : int.tryParse(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool get usesMaterialDesign {
|
||||
return _flutterDescriptor['uses-material-design'] ?? false;
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
final Directory appDirectory = fs.directory(app.appDirectory);
|
||||
await _addServicesToBundle(appDirectory);
|
||||
|
||||
updateGeneratedXcodeProperties(
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: fs.currentDirectory.path,
|
||||
buildInfo: buildInfo,
|
||||
targetOverride: targetOverride,
|
||||
@ -272,53 +272,6 @@ Future<XcodeBuildResult> buildXcodeProject({
|
||||
await fingerprinter.writeFingerprint();
|
||||
}
|
||||
|
||||
// If buildNumber is not specified, keep the project untouched.
|
||||
if (buildInfo.buildNumber != null) {
|
||||
final Status buildNumberStatus =
|
||||
logger.startProgress('Setting CFBundleVersion...', expectSlowOperation: true);
|
||||
try {
|
||||
final RunResult buildNumberResult = await runAsync(
|
||||
<String>[
|
||||
'/usr/bin/env',
|
||||
'xcrun',
|
||||
'agvtool',
|
||||
'new-version',
|
||||
'-all',
|
||||
buildInfo.buildNumber.toString(),
|
||||
],
|
||||
workingDirectory: app.appDirectory,
|
||||
);
|
||||
if (buildNumberResult.exitCode != 0) {
|
||||
throwToolExit('Xcode failed to set new version\n${buildNumberResult.stderr}');
|
||||
}
|
||||
} finally {
|
||||
buildNumberStatus.stop();
|
||||
}
|
||||
}
|
||||
|
||||
// If buildName is not specified, keep the project untouched.
|
||||
if (buildInfo.buildName != null) {
|
||||
final Status buildNameStatus =
|
||||
logger.startProgress('Setting CFBundleShortVersionString...', expectSlowOperation: true);
|
||||
try {
|
||||
final RunResult buildNameResult = await runAsync(
|
||||
<String>[
|
||||
'/usr/bin/env',
|
||||
'xcrun',
|
||||
'agvtool',
|
||||
'new-marketing-version',
|
||||
buildInfo.buildName,
|
||||
],
|
||||
workingDirectory: app.appDirectory,
|
||||
);
|
||||
if (buildNameResult.exitCode != 0) {
|
||||
throwToolExit('Xcode failed to set new marketing version\n${buildNameResult.stderr}');
|
||||
}
|
||||
} finally {
|
||||
buildNameStatus.stop();
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> buildCommands = <String>[
|
||||
'/usr/bin/env',
|
||||
'xcrun',
|
||||
|
@ -2,9 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../artifacts.dart';
|
||||
import '../base/common.dart';
|
||||
import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
@ -15,6 +18,7 @@ import '../base/utils.dart';
|
||||
import '../build_info.dart';
|
||||
import '../bundle.dart' as bundle;
|
||||
import '../cache.dart';
|
||||
import '../flutter_manifest.dart';
|
||||
import '../globals.dart';
|
||||
|
||||
final RegExp _settingExpr = new RegExp(r'(\w+)\s*=\s*(.*)$');
|
||||
@ -30,11 +34,11 @@ String _generatedXcodePropertiesPath(String projectPath) {
|
||||
|
||||
/// Writes default Xcode properties files in the Flutter project at [projectPath],
|
||||
/// if project is an iOS project and such files do not already exist.
|
||||
void generateXcodeProperties(String projectPath) {
|
||||
Future<void> generateXcodeProperties(String projectPath) async {
|
||||
if (fs.isDirectorySync(fs.path.join(projectPath, 'ios'))) {
|
||||
if (fs.file(_generatedXcodePropertiesPath(projectPath)).existsSync())
|
||||
return;
|
||||
updateGeneratedXcodeProperties(
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: projectPath,
|
||||
buildInfo: BuildInfo.debug,
|
||||
targetOverride: bundle.defaultMainPath,
|
||||
@ -47,12 +51,12 @@ void generateXcodeProperties(String projectPath) {
|
||||
///
|
||||
/// targetOverride: Optional parameter, if null or unspecified the default value
|
||||
/// from xcode_backend.sh is used 'lib/main.dart'.
|
||||
void updateGeneratedXcodeProperties({
|
||||
Future<void> updateGeneratedXcodeProperties({
|
||||
@required String projectPath,
|
||||
@required BuildInfo buildInfo,
|
||||
String targetOverride,
|
||||
@required bool previewDart2,
|
||||
}) {
|
||||
}) async {
|
||||
final StringBuffer localsBuffer = new StringBuffer();
|
||||
|
||||
localsBuffer.writeln('// This is a generated file; do not edit or check into version control.');
|
||||
@ -77,6 +81,24 @@ void updateGeneratedXcodeProperties({
|
||||
|
||||
localsBuffer.writeln('FLUTTER_FRAMEWORK_DIR=${flutterFrameworkDir(buildInfo.mode)}');
|
||||
|
||||
final String flutterManifest = fs.path.join(projectPath, bundle.defaultManifestPath);
|
||||
FlutterManifest manifest;
|
||||
try {
|
||||
manifest = await FlutterManifest.createFromPath(flutterManifest);
|
||||
} catch (error) {
|
||||
throwToolExit('Failed to load pubspec.yaml: $error');
|
||||
}
|
||||
|
||||
final String buildName = buildInfo?.buildName ?? manifest.buildName;
|
||||
if (buildName != null) {
|
||||
localsBuffer.writeln('FLUTTER_BUILD_NAME=$buildName');
|
||||
}
|
||||
|
||||
final int buildNumber = buildInfo?.buildNumber ?? manifest.buildNumber;
|
||||
if (buildNumber != null) {
|
||||
localsBuffer.writeln('FLUTTER_BUILD_NUMBER=$buildNumber');
|
||||
}
|
||||
|
||||
if (artifacts is LocalEngineArtifacts) {
|
||||
final LocalEngineArtifacts localEngineArtifacts = artifacts;
|
||||
localsBuffer.writeln('LOCAL_ENGINE=${localEngineArtifacts.engineOutPath}');
|
||||
|
@ -55,12 +55,12 @@ class FlutterProject {
|
||||
|
||||
/// Generates project files necessary to make Gradle builds work on Android
|
||||
/// and CocoaPods+Xcode work on iOS, for app projects only
|
||||
void ensureReadyForPlatformSpecificTooling() {
|
||||
Future<void> ensureReadyForPlatformSpecificTooling() async {
|
||||
if (!directory.existsSync() || hasExampleApp) {
|
||||
return;
|
||||
}
|
||||
injectPlugins(directory: directory.path);
|
||||
generateXcodeProperties(directory.path);
|
||||
await generateXcodeProperties(directory.path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ abstract class FlutterCommand extends Command<Null> {
|
||||
|
||||
if (shouldRunPub) {
|
||||
await pubGet(context: PubContext.getVerifyContext(name));
|
||||
new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
|
||||
await new FlutterProject(fs.currentDirectory).ensureReadyForPlatformSpecificTooling();
|
||||
}
|
||||
|
||||
setupApplicationPackages();
|
||||
|
@ -11,6 +11,16 @@ if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||
if (flutterVersionName == null) {
|
||||
throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
|
||||
@ -26,8 +36,8 @@ android {
|
||||
applicationId "{{androidIdentifier}}"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,16 @@ if (flutterRoot == null) {
|
||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||
if (flutterVersionCode == null) {
|
||||
throw new GradleException("versionCode not found. Define flutter.versionCode in the local.properties file.")
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||
if (flutterVersionName == null) {
|
||||
throw new GradleException("versionName not found. Define flutter.versionName in the local.properties file.")
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||
@ -31,8 +41,8 @@ android {
|
||||
applicationId "{{androidIdentifier}}"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -393,7 +393,7 @@
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -368,7 +368,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@ -396,7 +396,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -15,11 +15,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
@ -1,6 +1,14 @@
|
||||
name: {{projectName}}
|
||||
description: {{description}}
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# Read more about versioning at semver.org.
|
||||
version: 1.0.0+1
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
@ -2,16 +2,20 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/android/gradle.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../src/common.dart';
|
||||
import '../src/context.dart';
|
||||
|
||||
void main() {
|
||||
group('gradle build', () {
|
||||
test('do not crash if there is no Android SDK', () {
|
||||
test('do not crash if there is no Android SDK', () async {
|
||||
Exception shouldBeToolExit;
|
||||
try {
|
||||
// We'd like to always set androidSdk to null and test updateLocalProperties. But that's
|
||||
@ -21,7 +25,7 @@ void main() {
|
||||
// This test is written to fail if our bots get Android SDKs in the future: shouldBeToolExit
|
||||
// will be null and our expectation would fail. That would remind us to make these tests
|
||||
// hermetic before adding Android SDKs to the bots.
|
||||
updateLocalProperties();
|
||||
await updateLocalProperties();
|
||||
} on Exception catch (e) {
|
||||
shouldBeToolExit = e;
|
||||
}
|
||||
@ -126,4 +130,181 @@ someOtherProperty: someOtherValue
|
||||
expect(project.assembleTaskFor(const BuildInfo(BuildMode.release, 'unknown')), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('Gradle local.properties', () {
|
||||
Directory temp;
|
||||
|
||||
setUp(() {
|
||||
Cache.disableLocking();
|
||||
temp = fs.systemTempDirectory.createTempSync('flutter_tools');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
temp.deleteSync(recursive: true);
|
||||
});
|
||||
|
||||
Future<String> createMinimalProject(String manifest) async {
|
||||
final Directory directory = temp.childDirectory('android_project');
|
||||
final File manifestFile = directory.childFile('pubspec.yaml');
|
||||
manifestFile.createSync(recursive: true);
|
||||
manifestFile.writeAsStringSync(manifest);
|
||||
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
String propertyFor(String key, File file) {
|
||||
return file
|
||||
.readAsLinesSync()
|
||||
.where((String line) => line.startsWith('$key='))
|
||||
.map((String line) => line.split('=')[1])
|
||||
.first;
|
||||
}
|
||||
|
||||
Future<void> checkBuildVersion({
|
||||
String manifest,
|
||||
BuildInfo buildInfo,
|
||||
String expectedBuildName,
|
||||
String expectedBuildNumber,
|
||||
}) async {
|
||||
final String projectPath = await createMinimalProject(manifest);
|
||||
|
||||
try {
|
||||
await updateLocalProperties(projectPath: projectPath, buildInfo: buildInfo);
|
||||
|
||||
final String propertiesPath = fs.path.join(projectPath, 'android', 'local.properties');
|
||||
final File localPropertiesFile = fs.file(propertiesPath);
|
||||
|
||||
expect(propertyFor('flutter.versionName', localPropertiesFile), expectedBuildName);
|
||||
expect(propertyFor('flutter.versionCode', localPropertiesFile), expectedBuildNumber);
|
||||
} on Exception {
|
||||
// Android SDK not found, skip test
|
||||
}
|
||||
}
|
||||
|
||||
testUsingContext('extract build name and number from pubspec.yaml', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: '1',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('extract build name from pubspec.yaml', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: null,
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2');
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '1',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name and number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name and set number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to set build name and number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
@ -359,6 +361,118 @@ flutter:
|
||||
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||
expect(flutterManifest.isEmpty, false);
|
||||
});
|
||||
|
||||
Future<void> checkManifestVersion({
|
||||
String manifest,
|
||||
String expectedAppVersion,
|
||||
String expectedBuildName,
|
||||
int expectedBuildNumber,
|
||||
}) async {
|
||||
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||
expect(flutterManifest.appVersion, expectedAppVersion);
|
||||
expect(flutterManifest.buildName, expectedBuildName);
|
||||
expect(flutterManifest.buildNumber, expectedBuildNumber);
|
||||
}
|
||||
|
||||
test('parses major.minor.patch+build version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+2
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: '1.0.0+2',
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: 2,
|
||||
);
|
||||
});
|
||||
|
||||
test('parses major.minor+build version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0+2
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: '1.0+2',
|
||||
expectedBuildName: '1.0',
|
||||
expectedBuildNumber: 2,
|
||||
);
|
||||
});
|
||||
|
||||
test('parses major+build version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1+2
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: '1+2',
|
||||
expectedBuildName: '1',
|
||||
expectedBuildNumber: 2,
|
||||
);
|
||||
});
|
||||
|
||||
test('parses major version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: '1',
|
||||
expectedBuildName: '1',
|
||||
expectedBuildNumber: null,
|
||||
);
|
||||
});
|
||||
|
||||
test('parses empty version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: null,
|
||||
expectedBuildName: null,
|
||||
expectedBuildNumber: null,
|
||||
);
|
||||
});
|
||||
test('parses no version clause', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
await checkManifestVersion(
|
||||
manifest: manifest,
|
||||
expectedAppVersion: null,
|
||||
expectedBuildName: null,
|
||||
expectedBuildNumber: null,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('FlutterManifest with MemoryFileSystem', () {
|
||||
@ -371,8 +485,7 @@ dependencies:
|
||||
flutter:
|
||||
''';
|
||||
|
||||
final FlutterManifest flutterManifest = await FlutterManifest
|
||||
.createFromString(manifest);
|
||||
final FlutterManifest flutterManifest = await FlutterManifest.createFromString(manifest);
|
||||
expect(flutterManifest.isEmpty, false);
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,15 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/artifacts.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/bundle.dart' as bundle;
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
@ -277,14 +281,14 @@ Information about project "Runner":
|
||||
});
|
||||
}
|
||||
|
||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () {
|
||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile_arm'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
updateGeneratedXcodeProperties(
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
@ -297,14 +301,14 @@ Information about project "Runner":
|
||||
expect(contents.contains('ARCHS=armv7'), isTrue);
|
||||
});
|
||||
|
||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () {
|
||||
testUsingOsxContext('sets ARCHS=armv7 when armv7 local engine is set', () async {
|
||||
when(mockArtifacts.getArtifactPath(Artifact.flutterFramework, TargetPlatform.ios, any)).thenReturn('engine');
|
||||
when(mockArtifacts.engineOutPath).thenReturn(fs.path.join('out', 'ios_profile'));
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.debug, null,
|
||||
previewDart2: true,
|
||||
targetPlatform: TargetPlatform.ios,
|
||||
);
|
||||
updateGeneratedXcodeProperties(
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: 'path/to/project',
|
||||
buildInfo: buildInfo,
|
||||
previewDart2: true,
|
||||
@ -317,6 +321,185 @@ Information about project "Runner":
|
||||
expect(contents.contains('ARCHS=arm64'), isTrue);
|
||||
});
|
||||
});
|
||||
|
||||
group('Xcode Generated.xcconfig', () {
|
||||
Directory temp;
|
||||
|
||||
setUp(() {
|
||||
Cache.disableLocking();
|
||||
temp = fs.systemTempDirectory.createTempSync('flutter_tools');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
temp.deleteSync(recursive: true);
|
||||
});
|
||||
|
||||
Future<String> createMinimalProject(String manifest) async {
|
||||
final Directory directory = temp.childDirectory('ios_project');
|
||||
final File manifestFile = directory.childFile('pubspec.yaml');
|
||||
manifestFile.createSync(recursive: true);
|
||||
manifestFile.writeAsStringSync(manifest);
|
||||
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
String propertyFor(String key, File file) {
|
||||
final List<String> properties = file
|
||||
.readAsLinesSync()
|
||||
.where((String line) => line.startsWith('$key='))
|
||||
.map((String line) => line.split('=')[1])
|
||||
.toList();
|
||||
return properties.isEmpty ? null : properties.first;
|
||||
}
|
||||
|
||||
Future<void> checkBuildVersion({
|
||||
String manifest,
|
||||
BuildInfo buildInfo,
|
||||
String expectedBuildName,
|
||||
String expectedBuildNumber,
|
||||
}) async {
|
||||
final String projectPath = await createMinimalProject(manifest);
|
||||
|
||||
await updateGeneratedXcodeProperties(
|
||||
projectPath: projectPath,
|
||||
buildInfo: buildInfo,
|
||||
targetOverride: bundle.defaultMainPath,
|
||||
previewDart2: false,
|
||||
);
|
||||
|
||||
final String propertiesPath = fs.path.join(projectPath, 'ios', 'Flutter', 'Generated.xcconfig');
|
||||
final File localPropertiesFile = fs.file(propertiesPath);
|
||||
|
||||
expect(propertyFor('FLUTTER_BUILD_NAME', localPropertiesFile), expectedBuildName);
|
||||
expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), expectedBuildNumber);
|
||||
}
|
||||
|
||||
testUsingContext('extract build name and number from pubspec.yaml', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: '1',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('extract build name from pubspec.yaml', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: null,
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2');
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '1',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.0',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name and number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0+1
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to override build name and set number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
version: 1.0.0
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
|
||||
testUsingContext('allow build info to set build name and number', () async {
|
||||
const String manifest = '''
|
||||
name: test
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter:
|
||||
''';
|
||||
const BuildInfo buildInfo = const BuildInfo(BuildMode.release, null, buildName: '1.0.2', buildNumber: 3);
|
||||
await checkBuildVersion(
|
||||
manifest: manifest,
|
||||
buildInfo: buildInfo,
|
||||
expectedBuildName: '1.0.2',
|
||||
expectedBuildNumber: '3',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Platform fakePlatform(String name) {
|
||||
|
@ -20,23 +20,23 @@ void main() {
|
||||
group('ensure ready for platform-specific tooling', () {
|
||||
testInMemory('does nothing, if project is not created', () async {
|
||||
final FlutterProject project = someProject();
|
||||
project.ensureReadyForPlatformSpecificTooling();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.directory.existsSync(), isFalse);
|
||||
});
|
||||
testInMemory('does nothing in plugin or package root project', () async {
|
||||
final FlutterProject project = aPluginProject();
|
||||
project.ensureReadyForPlatformSpecificTooling();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isFalse);
|
||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isFalse);
|
||||
});
|
||||
testInMemory('injects plugins', () async {
|
||||
final FlutterProject project = aProjectWithIos();
|
||||
project.ensureReadyForPlatformSpecificTooling();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Runner/GeneratedPluginRegistrant.h').existsSync(), isTrue);
|
||||
});
|
||||
testInMemory('generates Xcode configuration', () async {
|
||||
final FlutterProject project = aProjectWithIos();
|
||||
project.ensureReadyForPlatformSpecificTooling();
|
||||
await project.ensureReadyForPlatformSpecificTooling();
|
||||
expect(project.ios.directory.childFile('Flutter/Generated.xcconfig').existsSync(), isTrue);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user