Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
98aeef2d
Unverified
Commit
98aeef2d
authored
Oct 09, 2020
by
Jenn Magder
Committed by
GitHub
Oct 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Build xcarchive command (#67598)
parent
98d1ad01
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
381 additions
and
52 deletions
+381
-52
ios_content_validation_test.dart
dev/devicelab/bin/tasks/ios_content_validation_test.dart
+23
-0
application_package.dart
packages/flutter_tools/lib/src/application_package.dart
+6
-0
build.dart
packages/flutter_tools/lib/src/commands/build.dart
+1
-0
build_ios.dart
packages/flutter_tools/lib/src/commands/build_ios.dart
+72
-23
mac.dart
packages/flutter_tools/lib/src/ios/mac.dart
+62
-29
build_xcarchive_test.dart
...ls/test/commands.shard/hermetic/build_xcarchive_test.dart
+216
-0
build_test.dart
...flutter_tools/test/general.shard/commands/build_test.dart
+1
-0
No files found.
dev/devicelab/bin/tasks/ios_content_validation_test.dart
View file @
98aeef2d
...
...
@@ -166,6 +166,29 @@ Future<void> main() async {
if
(!
await
localNetworkUsageFound
(
outputAppPath
))
{
throw
TaskResult
.
failure
(
'Debug bundle is missing NSLocalNetworkUsageDescription'
);
}
section
(
'Clean build'
);
await
inDirectory
(
flutterProject
.
rootPath
,
()
async
{
await
flutter
(
'clean'
);
});
section
(
'Archive'
);
await
inDirectory
(
flutterProject
.
rootPath
,
()
async
{
await
flutter
(
'build'
,
options:
<
String
>[
'xcarchive'
,
]);
});
checkDirectoryExists
(
path
.
join
(
flutterProject
.
rootPath
,
'build'
,
'ios'
,
'archive'
,
'Runner.xcarchive'
,
'Products'
,
));
});
return
TaskResult
.
success
(
null
);
...
...
packages/flutter_tools/lib/src/application_package.dart
View file @
98aeef2d
...
...
@@ -379,6 +379,12 @@ class BuildableIOSApp extends IOSApp {
@override
String
get
deviceBundlePath
=>
_buildAppPath
(
'iphoneos'
);
// Xcode uses this path for the final archive bundle location,
// not a top-level output directory.
// Specifying `build/ios/archive/Runner` will result in `build/ios/archive/Runner.xcarchive`.
String
get
archiveBundlePath
=>
globals
.
fs
.
path
.
join
(
getIosBuildDirectory
(),
'archive'
,
globals
.
fs
.
path
.
withoutExtension
(
_hostAppBundleName
));
String
_buildAppPath
(
String
type
)
{
return
globals
.
fs
.
path
.
join
(
getIosBuildDirectory
(),
type
,
_hostAppBundleName
);
}
...
...
packages/flutter_tools/lib/src/commands/build.dart
View file @
98aeef2d
...
...
@@ -28,6 +28,7 @@ class BuildCommand extends FlutterCommand {
buildSystem:
globals
.
buildSystem
,
verboseHelp:
verboseHelp
,
));
addSubcommand
(
BuildIOSArchiveCommand
(
verboseHelp:
verboseHelp
));
addSubcommand
(
BuildBundleCommand
(
verboseHelp:
verboseHelp
));
addSubcommand
(
BuildWebCommand
(
verboseHelp:
verboseHelp
));
addSubcommand
(
BuildMacosCommand
(
verboseHelp:
verboseHelp
));
...
...
packages/flutter_tools/lib/src/commands/build_ios.dart
View file @
98aeef2d
...
...
@@ -19,24 +19,8 @@ import 'build.dart';
/// Builds an .app for an iOS app to be used for local testing on an iOS device
/// or simulator. Can only be run on a macOS host. For producing deployment
/// .ipas, see https://flutter.dev/docs/deployment/ios.
class
BuildIOSCommand
extends
BuildSubCommand
{
BuildIOSCommand
({
@required
bool
verboseHelp
})
{
addTreeShakeIconsFlag
();
addSplitDebugInfoOption
();
addBuildModeFlags
(
defaultToRelease:
true
);
usesTargetOption
();
usesFlavorOption
();
usesPubOption
();
usesBuildNumberOption
();
usesBuildNameOption
();
addDartObfuscationOption
();
usesDartDefineOption
();
usesExtraFrontendOptions
();
addEnableExperimentation
(
hide:
!
verboseHelp
);
addBuildPerformanceFile
(
hide:
!
verboseHelp
);
addBundleSkSLPathOption
(
hide:
!
verboseHelp
);
addNullSafetyModeOptions
(
hide:
!
verboseHelp
);
usesAnalyzeSizeFlag
();
class
BuildIOSCommand
extends
_BuildIOSSubCommand
{
BuildIOSCommand
({
@required
bool
verboseHelp
})
:
super
(
verboseHelp:
verboseHelp
)
{
argParser
..
addFlag
(
'config-only'
,
help:
'Update the project configuration without performing a build. '
...
...
@@ -59,16 +43,76 @@ class BuildIOSCommand extends BuildSubCommand {
@override
final
String
description
=
'Build an iOS application bundle (Mac OS X host only).'
;
@override
final
XcodeBuildAction
xcodeBuildAction
=
XcodeBuildAction
.
build
;
@override
bool
get
forSimulator
=>
boolArg
(
'simulator'
);
@override
bool
get
configOnly
=>
boolArg
(
'config-only'
);
@override
bool
get
shouldCodesign
=>
boolArg
(
'codesign'
);
}
/// Builds an .xcarchive for an iOS app to be generated for App Store submission.
/// Can only be run on a macOS host.
/// For producing deployment .ipas, see https://flutter.dev/docs/deployment/ios.
class
BuildIOSArchiveCommand
extends
_BuildIOSSubCommand
{
BuildIOSArchiveCommand
({
@required
bool
verboseHelp
})
:
super
(
verboseHelp:
verboseHelp
);
@override
final
String
name
=
'xcarchive'
;
@override
final
String
description
=
'Build an iOS archive bundle (Mac OS X host only).'
;
@override
final
XcodeBuildAction
xcodeBuildAction
=
XcodeBuildAction
.
archive
;
@override
final
bool
forSimulator
=
false
;
@override
final
bool
configOnly
=
false
;
@override
final
bool
shouldCodesign
=
true
;
}
abstract
class
_BuildIOSSubCommand
extends
BuildSubCommand
{
_BuildIOSSubCommand
({
@required
bool
verboseHelp
})
{
addTreeShakeIconsFlag
();
addSplitDebugInfoOption
();
addBuildModeFlags
(
defaultToRelease:
true
);
usesTargetOption
();
usesFlavorOption
();
usesPubOption
();
usesBuildNumberOption
();
usesBuildNameOption
();
addDartObfuscationOption
();
usesDartDefineOption
();
usesExtraFrontendOptions
();
addEnableExperimentation
(
hide:
!
verboseHelp
);
addBuildPerformanceFile
(
hide:
!
verboseHelp
);
addBundleSkSLPathOption
(
hide:
!
verboseHelp
);
addNullSafetyModeOptions
(
hide:
!
verboseHelp
);
usesAnalyzeSizeFlag
();
}
@override
Future
<
Set
<
DevelopmentArtifact
>>
get
requiredArtifacts
async
=>
const
<
DevelopmentArtifact
>{
DevelopmentArtifact
.
iOS
,
};
XcodeBuildAction
get
xcodeBuildAction
;
bool
get
forSimulator
;
bool
get
configOnly
;
bool
get
shouldCodesign
;
@override
Future
<
FlutterCommandResult
>
runCommand
()
async
{
final
bool
forSimulator
=
boolArg
(
'simulator'
);
final
bool
configOnly
=
boolArg
(
'config-only'
);
final
bool
shouldCodesign
=
boolArg
(
'codesign'
);
defaultBuildMode
=
forSimulator
?
BuildMode
.
debug
:
BuildMode
.
release
;
final
BuildInfo
buildInfo
=
getBuildInfo
();
...
...
@@ -99,7 +143,11 @@ class BuildIOSCommand extends BuildSubCommand {
final
String
logTarget
=
forSimulator
?
'simulator'
:
'device'
;
final
String
typeName
=
globals
.
artifacts
.
getEngineType
(
TargetPlatform
.
ios
,
buildInfo
.
mode
);
globals
.
printStatus
(
'Building
$app
for
$logTarget
(
$typeName
)...'
);
if
(
xcodeBuildAction
==
XcodeBuildAction
.
build
)
{
globals
.
printStatus
(
'Building
$app
for
$logTarget
(
$typeName
)...'
);
}
else
{
globals
.
printStatus
(
'Archiving
$app
...'
);
}
final
XcodeBuildResult
result
=
await
buildXcodeProject
(
app:
app
,
buildInfo:
buildInfo
,
...
...
@@ -107,11 +155,12 @@ class BuildIOSCommand extends BuildSubCommand {
buildForDevice:
!
forSimulator
,
codesign:
shouldCodesign
,
configOnly:
configOnly
,
buildAction:
xcodeBuildAction
,
);
if
(!
result
.
success
)
{
await
diagnoseXcodeBuildFailure
(
result
,
globals
.
flutterUsage
,
globals
.
logger
);
throwToolExit
(
'Encountered error while
build
ing for
$logTarget
.'
);
throwToolExit
(
'Encountered error while
${xcodeBuildAction.name}
ing for
$logTarget
.'
);
}
if
(
buildInfo
.
codeSizeDirectory
!=
null
)
{
...
...
packages/flutter_tools/lib/src/ios/mac.dart
View file @
98aeef2d
...
...
@@ -96,6 +96,7 @@ Future<XcodeBuildResult> buildXcodeProject({
bool
codesign
=
true
,
String
deviceID
,
bool
configOnly
=
false
,
XcodeBuildAction
buildAction
=
XcodeBuildAction
.
build
,
})
async
{
if
(!
upgradePbxProjWithFlutterAssets
(
app
.
project
,
globals
.
logger
))
{
return
XcodeBuildResult
(
success:
false
);
...
...
@@ -321,6 +322,14 @@ Future<XcodeBuildResult> buildXcodeProject({
buildCommands
.
add
(
'COMPILER_INDEX_STORE_ENABLE=NO'
);
buildCommands
.
addAll
(
environmentVariablesAsXcodeBuildSettings
(
globals
.
platform
));
if
(
buildAction
==
XcodeBuildAction
.
archive
)
{
buildCommands
.
addAll
(<
String
>[
'-archivePath'
,
globals
.
fs
.
path
.
absolute
(
app
.
archiveBundlePath
),
'archive'
,
]);
}
final
Stopwatch
sw
=
Stopwatch
()..
start
();
initialBuildStatus
=
globals
.
logger
.
startProgress
(
'Running Xcode build...'
,
timeout:
timeoutConfiguration
.
slowOperation
);
...
...
@@ -333,13 +342,13 @@ Future<XcodeBuildResult> buildXcodeProject({
initialBuildStatus
?.
cancel
();
initialBuildStatus
=
null
;
globals
.
printStatus
(
'Xcode
build
done.'
.
padRight
(
kDefaultStatusPadding
+
1
)
'Xcode
${buildAction.name}
done.'
.
padRight
(
kDefaultStatusPadding
+
1
)
+
getElapsedAsSeconds
(
sw
.
elapsed
).
padLeft
(
5
),
);
globals
.
flutterUsage
.
sendTiming
(
'build'
,
'xcode-ios'
,
Duration
(
milliseconds:
sw
.
elapsedMilliseconds
));
globals
.
flutterUsage
.
sendTiming
(
buildAction
.
name
,
'xcode-ios'
,
Duration
(
milliseconds:
sw
.
elapsedMilliseconds
));
// Run -showBuildSettings again but with the exact same parameters as the
// build. showBuildSettings is reported to oc
as
sionally timeout. Here, we give
// build. showBuildSettings is reported to oc
ca
sionally timeout. Here, we give
// it a lot of wiggle room (locally on Flutter Gallery, this takes ~1s).
// When there is a timeout, we retry once. See issue #35988.
final
List
<
String
>
showBuildSettingsCommand
=
(
List
<
String
>
...
...
@@ -398,36 +407,42 @@ Future<XcodeBuildResult> buildXcodeProject({
),
);
}
else
{
// 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
);
if
(
buildAction
==
XcodeBuildAction
.
build
)
{
// 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'
);
}
globals
.
fsUtils
.
copyDirectorySync
(
globals
.
fs
.
directory
(
expectedOutputDirectory
)
,
globals
.
fs
.
directory
(
outputDir
)
,
final
String
expectedOutputDirectory
=
globals
.
fs
.
path
.
join
(
targetBuildDir
,
buildSettings
[
'WRAPPER_NAME'
]
,
);
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'
);
}
}
else
{
globals
.
printError
(
'Build succeeded but the expected app at
$expectedOutputDirectory
not found'
);
outputDir
=
'
${globals.fs.path.absolute(app.archiveBundlePath)}
.xcarchive'
;
if
(!
globals
.
fs
.
isDirectorySync
(
outputDir
))
{
globals
.
printError
(
'Archive succeeded but the expected xcarchive at
$outputDir
not found'
);
}
}
return
XcodeBuildResult
(
success:
true
,
...
...
@@ -568,6 +583,24 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
}
}
/// xcodebuild <buildaction> parameter (see man xcodebuild for details).
///
/// `clean`, `test`, `analyze`, and `install` are not supported.
enum
XcodeBuildAction
{
build
,
archive
}
extension
XcodeBuildActionExtension
on
XcodeBuildAction
{
String
get
name
{
switch
(
this
)
{
case
XcodeBuildAction
.
build
:
return
'build'
;
case
XcodeBuildAction
.
archive
:
return
'archive'
;
default
:
throw
UnsupportedError
(
'Unknown Xcode build action'
);
}
}
}
class
XcodeBuildResult
{
XcodeBuildResult
({
@required
this
.
success
,
...
...
packages/flutter_tools/test/commands.shard/hermetic/build_xcarchive_test.dart
0 → 100644
View file @
98aeef2d
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:file/memory.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/commands/build.dart'
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/reporting/reporting.dart'
;
import
'package:process/process.dart'
;
import
'../../src/common.dart'
;
import
'../../src/context.dart'
;
import
'../../src/testbed.dart'
;
class
FakeXcodeProjectInterpreterWithBuildSettings
extends
FakeXcodeProjectInterpreter
{
@override
Future
<
Map
<
String
,
String
>>
getBuildSettings
(
String
projectPath
,
{
String
scheme
,
Duration
timeout
=
const
Duration
(
minutes:
1
),
})
async
{
return
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'io.flutter.someProject'
,
'DEVELOPMENT_TEAM'
:
'abc'
,
};
}
}
final
Platform
macosPlatform
=
FakePlatform
(
operatingSystem:
'macos'
,
environment:
<
String
,
String
>{
'FLUTTER_ROOT'
:
'/'
,
}
);
final
Platform
notMacosPlatform
=
FakePlatform
(
operatingSystem:
'linux'
,
environment:
<
String
,
String
>{
'FLUTTER_ROOT'
:
'/'
,
}
);
void
main
(
)
{
FileSystem
fileSystem
;
Usage
usage
;
setUpAll
(()
{
Cache
.
disableLocking
();
});
setUp
(()
{
fileSystem
=
MemoryFileSystem
.
test
();
usage
=
Usage
.
test
();
});
// Sets up the minimal mock project files necessary to look like a Flutter project.
void
createCoreMockProjectFiles
()
{
fileSystem
.
file
(
'pubspec.yaml'
).
createSync
();
fileSystem
.
file
(
'.packages'
).
createSync
();
fileSystem
.
file
(
fileSystem
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
}
// Sets up the minimal mock project files necessary for iOS builds to succeed.
void
createMinimalMockProjectFiles
()
{
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
'ios'
,
'Runner.xcodeproj'
)).
createSync
(
recursive:
true
);
fileSystem
.
directory
(
fileSystem
.
path
.
join
(
'ios'
,
'Runner.xcworkspace'
)).
createSync
(
recursive:
true
);
fileSystem
.
file
(
fileSystem
.
path
.
join
(
'ios'
,
'Runner.xcodeproj'
,
'project.pbxproj'
)).
createSync
();
createCoreMockProjectFiles
();
}
const
FakeCommand
xattrCommand
=
FakeCommand
(
command:
<
String
>[
'xattr'
,
'-r'
,
'-d'
,
'com.apple.FinderInfo'
,
'/ios'
]);
// Creates a FakeCommand for the xcodebuild call to build the app
// in the given configuration.
FakeCommand
setUpMockXcodeBuildHandler
({
bool
verbose
=
false
,
bool
showBuildSettings
=
false
,
void
Function
()
onRun
})
{
return
FakeCommand
(
command:
<
String
>[
'/usr/bin/env'
,
'xcrun'
,
'xcodebuild'
,
'-configuration'
,
'Release'
,
if
(
verbose
)
'VERBOSE_SCRIPT_LOGGING=YES'
else
'-quiet'
,
'-workspace'
,
'Runner.xcworkspace'
,
'-scheme'
,
'Runner'
,
'BUILD_DIR=/build/ios'
,
'-sdk'
,
'iphoneos'
,
'FLUTTER_SUPPRESS_ANALYTICS=true'
,
'COMPILER_INDEX_STORE_ENABLE=NO'
,
'-archivePath'
,
'/build/ios/archive/Runner'
,
'archive'
,
if
(
showBuildSettings
)
'-showBuildSettings'
,
],
stdout:
'STDOUT STUFF'
,
onRun:
onRun
,
);
}
testUsingContext
(
'xcarchive build fails when there is no ios project'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
createCoreMockProjectFiles
();
expect
(
createTestCommandRunner
(
command
).
run
(
const
<
String
>[
'build'
,
'xcarchive'
,
'--no-pub'
]
),
throwsToolExit
(
message:
'Application not configured for iOS'
));
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
macosPlatform
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
XcodeProjectInterpreter:
()
=>
FakeXcodeProjectInterpreterWithBuildSettings
(),
});
testUsingContext
(
'xcarchive build fails on non-macOS platform'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
fileSystem
.
file
(
'pubspec.yaml'
).
createSync
();
fileSystem
.
file
(
'.packages'
).
createSync
();
fileSystem
.
file
(
fileSystem
.
path
.
join
(
'lib'
,
'main.dart'
))
.
createSync
(
recursive:
true
);
expect
(
createTestCommandRunner
(
command
).
run
(
const
<
String
>[
'build'
,
'xcarchive'
,
'--no-pub'
]
),
throwsToolExit
());
},
overrides:
<
Type
,
Generator
>{
Platform:
()
=>
notMacosPlatform
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
XcodeProjectInterpreter:
()
=>
FakeXcodeProjectInterpreterWithBuildSettings
(),
});
testUsingContext
(
'xcarchive build invokes xcode build'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
createMinimalMockProjectFiles
();
await
createTestCommandRunner
(
command
).
run
(
const
<
String
>[
'build'
,
'xcarchive'
,
'--no-pub'
]
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
list
(<
FakeCommand
>[
xattrCommand
,
setUpMockXcodeBuildHandler
(),
setUpMockXcodeBuildHandler
(
showBuildSettings:
true
),
]),
Platform:
()
=>
macosPlatform
,
XcodeProjectInterpreter:
()
=>
FakeXcodeProjectInterpreterWithBuildSettings
(),
});
testUsingContext
(
'xcarchive build invokes xcode build with verbosity'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
createMinimalMockProjectFiles
();
await
createTestCommandRunner
(
command
).
run
(
const
<
String
>[
'build'
,
'xcarchive'
,
'--no-pub'
,
'-v'
]
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
list
(<
FakeCommand
>[
xattrCommand
,
setUpMockXcodeBuildHandler
(
verbose:
true
),
setUpMockXcodeBuildHandler
(
verbose:
true
,
showBuildSettings:
true
),
]),
Platform:
()
=>
macosPlatform
,
XcodeProjectInterpreter:
()
=>
FakeXcodeProjectInterpreterWithBuildSettings
(),
});
testUsingContext
(
'Performs code size analysis and sends analytics'
,
()
async
{
final
BuildCommand
command
=
BuildCommand
();
createMinimalMockProjectFiles
();
fileSystem
.
file
(
'build/ios/Release-iphoneos/Runner.app/Frameworks/App.framework/App'
)
..
createSync
(
recursive:
true
)
..
writeAsBytesSync
(
List
<
int
>.
generate
(
10000
,
(
int
index
)
=>
0
));
// Capture Usage.test() events.
final
StringBuffer
buffer
=
await
capturedConsolePrint
(()
=>
createTestCommandRunner
(
command
).
run
(
const
<
String
>[
'build'
,
'xcarchive'
,
'--no-pub'
,
'--analyze-size'
]
)
);
expect
(
testLogger
.
statusText
,
contains
(
'A summary of your iOS bundle analysis can be found at'
));
expect
(
buffer
.
toString
(),
contains
(
'event {category: code-size-analysis, action: ios, label: null, value: null, cd33: '
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
FakeProcessManager
.
list
(<
FakeCommand
>[
xattrCommand
,
setUpMockXcodeBuildHandler
(
onRun:
()
{
fileSystem
.
file
(
'build/flutter_size_01/snapshot.arm64.json'
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'''[
{
"l": "dart:_internal",
"c": "SubListIterable",
"n": "[Optimized] skip",
"s": 2400
}
]'''
);
fileSystem
.
file
(
'build/flutter_size_01/trace.arm64.json'
)
..
createSync
(
recursive:
true
)
..
writeAsStringSync
(
'{}'
);
}),
setUpMockXcodeBuildHandler
(
showBuildSettings:
true
),
]),
Platform:
()
=>
macosPlatform
,
FileSystemUtils:
()
=>
FileSystemUtils
(
fileSystem:
fileSystem
,
platform:
macosPlatform
),
Usage:
()
=>
usage
,
XcodeProjectInterpreter:
()
=>
FakeXcodeProjectInterpreterWithBuildSettings
(),
});
}
packages/flutter_tools/test/general.shard/commands/build_test.dart
View file @
98aeef2d
...
...
@@ -29,6 +29,7 @@ void main() {
BuildWebCommand
(
verboseHelp:
false
),
BuildApkCommand
(
verboseHelp:
false
),
BuildIOSCommand
(
verboseHelp:
false
),
BuildIOSArchiveCommand
(
verboseHelp:
false
),
BuildAppBundleCommand
(
verboseHelp:
false
),
BuildFuchsiaCommand
(
verboseHelp:
false
),
BuildAarCommand
(
verboseHelp:
false
),
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment