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
7e02cc34
Unverified
Commit
7e02cc34
authored
Mar 05, 2021
by
Jenn Magder
Committed by
GitHub
Mar 05, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bitcode strip Flutter.framework in assemble build target (#77329)
parent
565e4877
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
151 additions
and
33 deletions
+151
-33
ios.dart
dev/devicelab/lib/framework/ios.dart
+1
-1
xcode_backend.sh
packages/flutter_tools/bin/xcode_backend.sh
+1
-6
ios.dart
packages/flutter_tools/lib/src/build_system/targets/ios.dart
+38
-16
ios_test.dart
...ols/test/general.shard/build_system/targets/ios_test.dart
+110
-9
darwin_common.dart
packages/flutter_tools/test/src/darwin_common.dart
+1
-1
No files found.
dev/devicelab/lib/framework/ios.dart
View file @
7e02cc34
...
...
@@ -42,7 +42,7 @@ Future<bool> containsBitcode(String pathToBinary) async {
if
(
line
.
contains
(
'segname __LLVM'
)
&&
lines
.
length
-
index
-
1
>
3
)
{
final
String
emptyBitcodeMarker
=
lines
.
skip
(
index
-
1
)
.
take
(
3
)
.
take
(
4
)
.
firstWhere
(
(
String
line
)
=>
line
.
contains
(
' size 0x0000000000000001'
),
orElse:
()
=>
null
,
...
...
packages/flutter_tools/bin/xcode_backend.sh
View file @
7e02cc34
...
...
@@ -137,9 +137,8 @@ is set to release or run \"flutter build ios --release\", then re-run Archive fr
local_engine_flag
=
"--local-engine=
${
LOCAL_ENGINE
}
"
flutter_framework
=
"
${
FLUTTER_ENGINE
}
/out/
${
LOCAL_ENGINE
}
/Flutter.xcframework"
fi
local
bitcode_flag
=
""
if
[[
"
$ENABLE_BITCODE
"
==
"YES"
]]
;
then
if
[[
"
$ENABLE_BITCODE
"
==
"YES"
&&
"
$ACTION
"
==
"install"
]]
;
then
bitcode_flag
=
"true"
fi
...
...
@@ -218,10 +217,6 @@ EmbedFlutterFrameworks() {
# Copy Xcode behavior and don't copy over headers or modules.
RunCommand rsync
-av
--delete
--filter
"- .DS_Store"
--filter
"- Headers"
--filter
"- Modules"
"
${
BUILT_PRODUCTS_DIR
}
/Flutter.framework"
"
${
xcode_frameworks_dir
}
/"
if
[[
"
$ACTION
"
!=
"install"
||
"
$ENABLE_BITCODE
"
==
"NO"
]]
;
then
# Strip bitcode from the destination unless archiving, or if bitcode is disabled entirely.
RunCommand
"
${
DT_TOOLCHAIN_DIR
}
"
/usr/bin/bitcode_strip
"
${
BUILT_PRODUCTS_DIR
}
/Flutter.framework/Flutter"
-r
-o
"
${
xcode_frameworks_dir
}
/Flutter.framework/Flutter"
fi
# Sign the binaries we moved.
if
[[
-n
"
${
EXPANDED_CODE_SIGN_IDENTITY
:-}
"
]]
;
then
...
...
packages/flutter_tools/lib/src/build_system/targets/ios.dart
View file @
7e02cc34
...
...
@@ -280,8 +280,18 @@ abstract class UnpackIOS extends Target {
if
(
environment
.
defines
[
kIosArchs
]
==
null
)
{
throw
MissingDefineException
(
kIosArchs
,
name
);
}
if
(
environment
.
defines
[
kBitcodeFlag
]
==
null
)
{
throw
MissingDefineException
(
kBitcodeFlag
,
name
);
}
await
_copyFramework
(
environment
);
await
_thinFramework
(
environment
);
final
File
frameworkBinary
=
environment
.
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
);
final
String
frameworkBinaryPath
=
frameworkBinary
.
path
;
if
(!
frameworkBinary
.
existsSync
())
{
throw
Exception
(
'Binary
$frameworkBinaryPath
does not exist, cannot thin'
);
}
await
_thinFramework
(
environment
,
frameworkBinaryPath
);
await
_bitcodeStripFramework
(
environment
,
frameworkBinaryPath
);
}
Future
<
void
>
_copyFramework
(
Environment
environment
)
async
{
...
...
@@ -312,37 +322,30 @@ abstract class UnpackIOS extends Target {
}
/// Destructively thin Flutter.framework to include only the specified architectures.
Future
<
void
>
_thinFramework
(
Environment
environment
)
async
{
final
Directory
frameworkDirectory
=
environment
.
outputDir
;
final
File
flutterFramework
=
frameworkDirectory
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
);
final
String
binaryPath
=
flutterFramework
.
path
;
if
(!
flutterFramework
.
existsSync
())
{
throw
Exception
(
'Binary
$binaryPath
does not exist, cannot thin'
);
}
Future
<
void
>
_thinFramework
(
Environment
environment
,
String
frameworkBinaryPath
)
async
{
final
String
archs
=
environment
.
defines
[
kIosArchs
];
final
List
<
String
>
archList
=
archs
.
split
(
' '
).
toList
();
final
ProcessResult
infoResult
=
environment
.
processManager
.
runSync
(<
String
>[
'lipo'
,
'-info'
,
b
inaryPath
,
frameworkB
inaryPath
,
]);
final
String
lipoInfo
=
infoResult
.
stdout
as
String
;
final
ProcessResult
verifyResult
=
environment
.
processManager
.
runSync
(<
String
>[
'lipo'
,
b
inaryPath
,
frameworkB
inaryPath
,
'-verify_arch'
,
...
archList
]);
if
(
verifyResult
.
exitCode
!=
0
)
{
throw
Exception
(
'Binary
$
b
inaryPath
does not contain
$archs
. Running lipo -info:
\n
$lipoInfo
'
);
throw
Exception
(
'Binary
$
frameworkB
inaryPath
does not contain
$archs
. Running lipo -info:
\n
$lipoInfo
'
);
}
// Skip thinning for non-fat executables.
if
(
lipoInfo
.
startsWith
(
'Non-fat file:'
))
{
environment
.
logger
.
printTrace
(
'Skipping lipo for non-fat file
$
b
inaryPath
'
);
environment
.
logger
.
printTrace
(
'Skipping lipo for non-fat file
$
frameworkB
inaryPath
'
);
return
;
}
...
...
@@ -350,17 +353,36 @@ abstract class UnpackIOS extends Target {
final
ProcessResult
extractResult
=
environment
.
processManager
.
runSync
(<
String
>[
'lipo'
,
'-output'
,
b
inaryPath
,
frameworkB
inaryPath
,
for
(
final
String
arch
in
archList
)
...<
String
>[
'-extract'
,
arch
,
],
...<
String
>[
b
inaryPath
],
...<
String
>[
frameworkB
inaryPath
],
]);
if
(
extractResult
.
exitCode
!=
0
)
{
throw
Exception
(
'Failed to extract
$archs
for
$binaryPath
.
\n
${extractResult.stderr}
\n
Running lipo -info:
\n
$lipoInfo
'
);
throw
Exception
(
'Failed to extract
$archs
for
$frameworkBinaryPath
.
\n
${extractResult.stderr}
\n
Running lipo -info:
\n
$lipoInfo
'
);
}
}
/// Destructively strip bitcode from the framework, if needed.
Future
<
void
>
_bitcodeStripFramework
(
Environment
environment
,
String
frameworkBinaryPath
)
async
{
if
(
environment
.
defines
[
kBitcodeFlag
]
==
'true'
)
{
return
;
}
final
ProcessResult
stripResult
=
environment
.
processManager
.
runSync
(<
String
>[
'xcrun'
,
'bitcode_strip'
,
frameworkBinaryPath
,
'-m'
,
// leave the bitcode marker.
'-o'
,
frameworkBinaryPath
,
]);
if
(
stripResult
.
exitCode
!=
0
)
{
throw
Exception
(
'Failed to strip bitcode for
$frameworkBinaryPath
.
\n
${stripResult.stderr}
'
);
}
}
}
...
...
packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
View file @
7e02cc34
...
...
@@ -239,7 +239,7 @@ void main() {
Platform:
()
=>
macPlatform
,
});
group
(
'copy
and thin
engine Flutter.framework'
,
()
{
group
(
'copy
, thin, and bitcode strip
engine Flutter.framework'
,
()
{
Directory
outputDir
;
FakeCommand
copyPhysicalFrameworkCommand
;
...
...
@@ -269,6 +269,7 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'x86_64'
,
kSdkRoot:
'path/to/iPhoneSimulator.sdk'
,
kBitcodeFlag:
'true'
,
},
);
...
...
@@ -308,7 +309,7 @@ void main() {
expect
(
processManager
.
hasRemainingExpectations
,
isFalse
);
});
testWithoutContext
(
'
thinning
fails when frameworks missing'
,
()
async
{
testWithoutContext
(
'fails when frameworks missing'
,
()
async
{
final
Environment
environment
=
Environment
.
test
(
fileSystem
.
currentDirectory
,
processManager:
processManager
,
...
...
@@ -319,10 +320,11 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'arm64'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
''
,
},
);
processManager
.
addCommand
(
copyPhysicalFrameworkCommand
);
expect
(
await
expectLater
(
const
DebugUnpackIOS
().
build
(
environment
),
throwsA
(
isA
<
Exception
>().
having
(
(
Exception
exception
)
=>
exception
.
toString
(),
...
...
@@ -331,7 +333,7 @@ void main() {
)));
});
testWithoutContext
(
'
thinning
fails when requested archs missing from framework'
,
()
async
{
testWithoutContext
(
'fails when requested archs missing from framework'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
...
...
@@ -344,6 +346,7 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'arm64 armv7'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
''
,
},
);
...
...
@@ -366,7 +369,7 @@ void main() {
],
exitCode:
1
),
);
expect
(
await
expectLater
(
const
DebugUnpackIOS
().
build
(
environment
),
throwsA
(
isA
<
Exception
>().
having
(
(
Exception
exception
)
=>
exception
.
toString
(),
...
...
@@ -375,7 +378,7 @@ void main() {
)));
});
testWithoutContext
(
'
thinning
fails when lipo extract fails'
,
()
async
{
testWithoutContext
(
'fails when lipo extract fails'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
...
...
@@ -388,6 +391,7 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'arm64 armv7'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
''
,
},
);
...
...
@@ -424,7 +428,7 @@ void main() {
stderr:
'lipo error'
),
);
expect
(
await
expectLater
(
const
DebugUnpackIOS
().
build
(
environment
),
throwsA
(
isA
<
Exception
>().
having
(
(
Exception
exception
)
=>
exception
.
toString
(),
...
...
@@ -433,7 +437,7 @@ void main() {
)));
});
testWithoutContext
(
'skips thin framework
s
'
,
()
async
{
testWithoutContext
(
'skips thin framework'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
...
...
@@ -446,6 +450,7 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'arm64'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
'true'
,
},
);
...
...
@@ -473,7 +478,7 @@ void main() {
expect
(
processManager
.
hasRemainingExpectations
,
isFalse
);
});
testWithoutContext
(
'thins fat framework
s
'
,
()
async
{
testWithoutContext
(
'thins fat framework'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
...
...
@@ -486,6 +491,7 @@ void main() {
defines:
<
String
,
String
>{
kIosArchs:
'arm64 armv7'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
'true'
,
},
);
...
...
@@ -524,5 +530,100 @@ void main() {
await
const
DebugUnpackIOS
().
build
(
environment
);
expect
(
processManager
.
hasRemainingExpectations
,
isFalse
);
});
testWithoutContext
(
'fails when bitcode strip fails'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
fileSystem
.
currentDirectory
,
processManager:
processManager
,
artifacts:
artifacts
,
logger:
logger
,
fileSystem:
fileSystem
,
outputDir:
outputDir
,
defines:
<
String
,
String
>{
kIosArchs:
'arm64'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
''
,
},
);
processManager
.
addCommands
(<
FakeCommand
>[
copyPhysicalFrameworkCommand
,
FakeCommand
(
command:
<
String
>[
'lipo'
,
'-info'
,
binary
.
path
,
],
stdout:
'Non-fat file:'
),
FakeCommand
(
command:
<
String
>[
'lipo'
,
binary
.
path
,
'-verify_arch'
,
'arm64'
,
]),
FakeCommand
(
command:
<
String
>[
'xcrun'
,
'bitcode_strip'
,
binary
.
path
,
'-m'
,
'-o'
,
binary
.
path
,
],
exitCode:
1
,
stderr:
'bitcode_strip error'
),
]);
await
expectLater
(
const
DebugUnpackIOS
().
build
(
environment
),
throwsA
(
isA
<
Exception
>().
having
(
(
Exception
exception
)
=>
exception
.
toString
(),
'description'
,
contains
(
'Failed to strip bitcode for output/Flutter.framework/Flutter.
\n
bitcode_strip error'
),
)));
expect
(
processManager
.
hasRemainingExpectations
,
isFalse
);
});
testWithoutContext
(
'strips framework'
,
()
async
{
final
File
binary
=
outputDir
.
childDirectory
(
'Flutter.framework'
).
childFile
(
'Flutter'
)..
createSync
(
recursive:
true
);
final
Environment
environment
=
Environment
.
test
(
fileSystem
.
currentDirectory
,
processManager:
processManager
,
artifacts:
artifacts
,
logger:
logger
,
fileSystem:
fileSystem
,
outputDir:
outputDir
,
defines:
<
String
,
String
>{
kIosArchs:
'arm64'
,
kSdkRoot:
'path/to/iPhoneOS.sdk'
,
kBitcodeFlag:
''
,
},
);
processManager
.
addCommands
(<
FakeCommand
>[
copyPhysicalFrameworkCommand
,
FakeCommand
(
command:
<
String
>[
'lipo'
,
'-info'
,
binary
.
path
,
],
stdout:
'Non-fat file:'
),
FakeCommand
(
command:
<
String
>[
'lipo'
,
binary
.
path
,
'-verify_arch'
,
'arm64'
,
]),
FakeCommand
(
command:
<
String
>[
'xcrun'
,
'bitcode_strip'
,
binary
.
path
,
'-m'
,
'-o'
,
binary
.
path
,
]),
]);
await
const
DebugUnpackIOS
().
build
(
environment
);
expect
(
processManager
.
hasRemainingExpectations
,
isFalse
);
});
});
}
packages/flutter_tools/test/src/darwin_common.dart
View file @
7e02cc34
...
...
@@ -40,7 +40,7 @@ bool containsBitcode(String pathToBinary, ProcessManager processManager) {
lines
.
asMap
().
forEach
((
int
index
,
String
line
)
{
if
(
line
.
contains
(
'segname __LLVM'
)
&&
lines
.
length
-
index
-
1
>
3
)
{
final
String
emptyBitcodeMarker
=
lines
.
skip
(
index
-
1
).
take
(
3
).
firstWhere
(
lines
.
skip
(
index
-
1
).
take
(
4
).
firstWhere
(
(
String
line
)
=>
line
.
contains
(
' size 0x0000000000000001'
),
orElse:
()
=>
null
,
);
...
...
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