-
Notifications
You must be signed in to change notification settings - Fork 6k
Handle Flutter assets outside FLX #4343
Conversation
76ac034 to
48ecfbd
Compare
|
Instead of defining a very specifically named directory along with paths within that directory in which to find certain assets, I think it would be better to make the APIs explicitly take the paths (or buffers) to the individual artifacts. This gives us the most flexibility moving forward. This, along with the fact that this change will break embedders makes me wary of landing this patch. We should be able to make header compatible updates to the public API to accomodate this change. |
| std::vector<uint8_t>* data, | ||
| std::unique_ptr<DirectoryAssetBundle>& directory_asset_bundle, | ||
| fxl::RefPtr<ZipAssetStore>& asset_store) { | ||
| return (directory_asset_bundle && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we maybe split this up into multiple lines with early returns on failure conditions for readability?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could probably be split up, but there are no failure conditions as such here. The best we could do would be something like
if (directory_asset_bundle &&
directory_asset_bundle->GetAsBuffer(name, data)) {
return true;
}
return asset_store && asset_store->GetAsBuffer(name, data);(I kind of prefer the current version, though, which is copied from engine. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I didn't realize this was copied directly from the engine. Our preferences don't match but I don't have a strong opinion about this. Lets keep it as it.
| @property(nonatomic, readonly) NSURL* dartMain; | ||
| @property(nonatomic, readonly) NSURL* packages; | ||
| @property(nonatomic, readonly) NSURL* flxArchive; | ||
| @property(nonatomic, readonly) NSURL* flutterAssets; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is modifying a header that is published as part of the Flutter.framework. Existing users of the framework (iOS embedders) will break if they are currently using this API. We should decide whether to keep this API as-is and have the initializer return nil when queried with FLX assets for the sake of backwards header compatibility. We don't want to get into a situation where a Flutter upgrade causes the developer's embedder to break. I would land this patch once all the changes that remove FLXs are consolidated and we can make one breaking change along with notifications on appropriate channels and changelogs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change above is not in the public API, however the change in FlutterDartProject.h is, and I agree with postponing the breaking change until FLX is completely removed. I'll change this PR to keep the FLX initializer and add an initializer with Flutter assets directory, WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be a breaking change once we stop putting assets in app.flx anyway, so we might as well break it (with the right notices, of course) once.
Since no-one reads notices ahead of time anyway, I think I'd prefer to find out about this by having my build break up front, rather than having the build work but assets mysteriously no longer appear in my app. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change this PR to keep the FLX initializer and add an initializer with Flutter assets directory, WDYT?
Sounds good to me.
This will be a breaking change once we stop putting assets in
app.flxanyway, so we might as well break it (with the right notices, of course) once.
Since we will be updating the engine and the supporting tooling (that generates the FLX files and configures application launch) in one go, there should be no runtime misbehavior due to the embedder looking for, but not finding the FLX in a particular spot. However, embedders using the old API will break even though those APIs will never be invoked by the application launch mechanism.
Since no-one reads notices ahead of time anyway, I think I'd prefer to find out about this by having my build break up front,
A kinder, more tactful, approach in dealing with this update would be to decorate the old API with NS_DEPRECATED attributes with a clear message regarding the direction we are going to take moving forward and what the user should do to rectify the warning. Adroit users already have warnings set as errors and will be able to handle the update on their own (especially if we indicate that the old API is a no-op that the application launch mechanism wont invoke anyway). Users who are perhaps less familar with the native side of mobile development and build systems wont have their builds break on them due to a routine update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mentioned a doc with instructions on how this should be done. Are you able to find it? If not, could you please let me know more specifically how to do the tagging, and the update of the changelog etc. ?
szakarias
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that relying on specific names is less transparent and should be avoided when possible, however I am not sure if we can do it here. The tooling on iOS only includes project files listed in the project.pbxproj which is part of the flutter create template. Hence we need a specifically named directory in which to place Flutter artifacts. If you know of a way around this, it would be great.
| @property(nonatomic, readonly) NSURL* dartMain; | ||
| @property(nonatomic, readonly) NSURL* packages; | ||
| @property(nonatomic, readonly) NSURL* flxArchive; | ||
| @property(nonatomic, readonly) NSURL* flutterAssets; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change above is not in the public API, however the change in FlutterDartProject.h is, and I agree with postponing the breaking change until FLX is completely removed. I'll change this PR to keep the FLX initializer and add an initializer with Flutter assets directory, WDYT?
jakobr-google
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but defer to @chinmaygarde.
| std::vector<uint8_t>* data, | ||
| std::unique_ptr<DirectoryAssetBundle>& directory_asset_bundle, | ||
| fxl::RefPtr<ZipAssetStore>& asset_store) { | ||
| return (directory_asset_bundle && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could probably be split up, but there are no failure conditions as such here. The best we could do would be something like
if (directory_asset_bundle &&
directory_asset_bundle->GetAsBuffer(name, data)) {
return true;
}
return asset_store && asset_store->GetAsBuffer(name, data);(I kind of prefer the current version, though, which is copied from engine. :)
runtime/dart_init.cc
Outdated
| zip_asset_store = fxl::MakeRefCounted<ZipAssetStore>( | ||
| GetUnzipperProviderForPath(flx_path)); | ||
| } | ||
| GetAssetAsBuffer(kKernelAssetKey, &kernel_data, directory_asset_, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
directory_asset_bundle?
| } | ||
| InputStream is = null; | ||
| OutputStream os = null; | ||
| try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not your code, but if we're on a modern Java version (>=7), we should be able to do
try (InputStream is = manager.open(asset)) {
try (OutputStream os = new FileOutputStream(output)) {
...
}
}And not have to bother with the nested finally/try/if/finally/... mess.
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
| // Default to "app.flx" | ||
| flxName = @"app"; | ||
| - (NSString*)pathForFlutterAssetsFromBundle:(NSBundle*)bundle { | ||
| NSString* flutterAssetsName = [bundle objectForInfoDictionaryKey:@"FLTFlxName"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still the right key, or should we use something like FLTAssetsPath?
(The key isn't defined in our template's Info.plist, so I don't know if anyone's actually using this.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't been able to find any usages. I'll keep it with an updated key name so that it is still configurable in Info.plist.
| @property(nonatomic, readonly) NSURL* dartMain; | ||
| @property(nonatomic, readonly) NSURL* packages; | ||
| @property(nonatomic, readonly) NSURL* flxArchive; | ||
| @property(nonatomic, readonly) NSURL* flutterAssets; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be a breaking change once we stop putting assets in app.flx anyway, so we might as well break it (with the right notices, of course) once.
Since no-one reads notices ahead of time anyway, I think I'd prefer to find out about this by having my build break up front, rather than having the build work but assets mysteriously no longer appear in my app. :)
|
Github won't let me reply to some of the comments inline. So adding replies to specific comments here:
We already have a hook into the build system via
Lets add |
18c6dbd to
cc66d15
Compare
|
I looked into |
f4af7a0 to
3126059
Compare
|
@chinmaygarde would it be possible for you to have a look at the changes? Maybe we can wait with the deprecation part in order to move this forward as I now have a couple of PRs depending on this. |
|
@szakarias I have drawn up a proposal for how we could manage breaking API changes in the public engine API. To help with the deprecations, a few macros were introduced in this pull request. Can you decorate the deprecated methods with the same and add a note in the changelog as mentioned in the document please? |
|
Users of the public embedder API (non iOS or Android embedders) will break because of the updates in the current version of that patch. For backward compatibility, I suggest you still attempt to initialize the asset bundle from the path if it is a regular file (you are returning early with a log message currently). If it is a directory, then you can initialize the directory asset bundle and then the zip asset store with an optional |
e9b9e08 to
838bbaf
Compare
|
Thanks for the comments! PTAL. Decorated the deprecated methods, and also reverted the change in asset retrieval. We still return assets as byte data instead of the asset paths. I am postponing this to a later change. Updated the flutter PR correspondingly. |
jakobr-google
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| "This initializer is no longer used since the FLX will be deprecated. " | ||
| "Instead, use [initWithFlutterAssets]."); | ||
|
|
||
| - (instancetype)initWithFLXArchiveWithScriptSnapshot:(NSURL*)flutterAssetsURL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Shouldn't it still be archiveURL here?
Requested changes were made.
838bbaf to
d4a30e0
Compare
d4a30e0 to
ece8080
Compare
|
@szakarias have you tried running flutter examples with these changes? |
|
cc'ing @crelier who is doing dart-engine-flutter roll today as this is potential blocker for flutter engine to flutter tools roll. |
|
@aam, it is my turn to do a Dart roll, but the flutter gallery is not running correctly: regis@belenos:~/flutter/examples/flutter_gallery$ flutter run --release --local-engine=android_release FAILURE: Build failed with an exception.
|
|
Yes @crelier , I would try to verify that at 28bc7b1 of flutter engine things are looking good(they did for me, but I only looked at debug) and then unless there is a response from @szakarias rollback three seemingly related commits by @szakarias from earlier this morning to get back to that 28bc7b1, roll from there. |
|
@aam, a debug run is failing too. So I'll wait until this gets fix to continue with the dart roll. |
|
I believe @szakarias has two related PRs on flutter/flutter that might need to go in with the engine roll. Could you see if applying flutter/flutter#12944 (and maybe also flutter/flutter#13011) fix the blank screen issue? The snapshotter issue looks unrelated, but I don't know. |
|
flutter/flutter#12944 and flutter/flutter#13011 are merged now. |
| FlutterMain.class.getName() + '.' + FLX_KEY; | ||
| public static final String PUBLIC_SNAPSHOT_BLOB_KEY = | ||
| FlutterMain.class.getName() + '.' + SNAPSHOT_BLOB_KEY; | ||
| public static final String PUBLIC_FLUTTER_ASSETS_DIR_KEY = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this was never wired up in initConfig(), so even if apps specify this key in their manifest, we're still looking in the default assets dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, thanks!
This is another step towards removing
app.flx.A
flutter_assetsdirectory is introduced and engine is now invoked with the path to this.If present, the snapshot is read from
flutter_assetsand queries on the asset channel will be answered with the path to the asset.On Android we add the
flutter_assetsdirectory and its content to the app's data directory by handling directories in the ResourceExtractor.Some files are still read from
app.flx. This will be cleaned up in a follow up PR.This is a breaking change since the initializers in FlutterDartProject.h are renamed.
Companion Flutter PR flutter/flutter#12944