While trying to figure out how best to use runtime_deps to generate a .isolate file for Android, I'm now questioning whether we should redesign how we handle app data entirely! Here's what we currently have:
1. Desktop platforms: data / data_deps produce a list of files required at runtime.
2. Android: android_assets() specify files to be packed into the .apk's as assets/ directory
3. iOS: bundle_data() specify files to be copied into a final .bundle directory
4. Android unit tests: Use a checked in .isolate file to list files that should be side-loaded to the device before tests can be run.
#4 is what I've been working / thinking about lately, and it's just not going well. Right now I've hacked together a change to GN to write out runtime_deps, and then a python script which blacklists 90% of the entries in it. Ugly!
I'm wondering if we could come up with an actual x-platform system for specifying runtime deps?
Some design considerations I think are true (please let me know if I'm wrong):
1. Assets are compressed by default on Android, but we specify that some be uncompressed in order to mmap them
2. Both iOS and Android need to be able to control packaging of these deps at build-time
- This includes ability to rename files (Android v8 snapshots do this for _32 and _64)
3. All runtime deps are read-only
4. Runtime deps do not need to support enumeration at runtime
Here's the strawman:
1. Get rid of data / data_deps in favour of bundle_data
2. Make the existing "runtime_deps" logic of GN apply only to shared libs (aka, the part of data that isn't explicitly listed in .gn files)
3. Mark files as needing to be uncompressed via a special {{marker}}:
E.g. outputs=["{{uncompressed_bundle_resources_dir}}/{{source_file_part}}"]
4. Create an API in base that fetches a file from bundle_data in an x-platform way.
Option A for an API:
class AssetManager {
Asset Open(FilePath asset_path)
}
class Asset {
bool IsValid(); // Whether the asset exists.
MemoryMappedFile Map();
int64_t GetSize();
int Read(int64_t offset, char* data, int size); // Works even when compressed.
}
There are ~200 references to DIR_TEST_DATA, and following just a few led me to net/base/file_stream_context.cc. Such a change looks to be *months* of work.
Option B for an API:
class AssetManager {
File Open(FilePath asset_path)
MemoryMappedFile OpenMapped(FilePath asset_path)
FilePath PathForAsset(FilePath asset_path) --> app-asset://$asset_path
}
To make File handle this, we'd need it to add "if (IsAsset())" to almost every function, at least for OS_ANDROID where it's not actually a file we're dealing with.
Option C for an API:
- Same as B, except we use
pipes to create an fd that represents a portion of the .apk
- This kind of sucks since each pipe requires a dedicated thread to feed it.
Option D for an API:
- Same as A, except for tests we extract all assets on launch and set DIR_TEST_DATA accordingly.
Any other options? Opinions as to whether this is even a problem worth solving?