-
Notifications
You must be signed in to change notification settings - Fork 205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a compile-time constant for platform #1889
Comments
@alexeyinkin I think it could be possible. Currently, the better way to do this is by using Dart defines, which are resolved at compile-time, but I agree that they are a little more error-prone. This question seems to not belong to this repo, that is concerned with language evolution, but to |
cc @lrhn |
To summarise some discussions we had between @mit-mit @lrhn and me. One of the approaches we could adopt now is to lean on environment constants more and change the code that does system detection in a way that allows its runtime behaviour to be overriden / short-circuited though environment constants. This means we would rewrite the code that does this: class Platform {
// Can't be analyzed by the compiler.
external static bool get isLinux;
} into something like this class Platform {
@pragma('vm:external-name', 'f')
external static bool _isLinuxImpl();
static const _isLinuxFromOverride =
String.fromEnvironment('os.override') == 'linux';
static bool get isLinux => const bool.hasEnvironment('os.override')
? _isLinuxFromOverride
: _isLinuxImpl();
} This way build system could set @lrhn is changing We have also considered to apply the same pattern to
In the end we might need to simply special case |
May I ask why we make this an optional override? It means sometimes kernel ASTs know their target OS/Arch/... and sometimes not. This puts us in an awkward spot where Kernel ASTs are seemingly target independent but not always - which seems a little fishy to me. If we made it mandatory to know the target OS/Arch/... when producing Kernel ASTs we could also remove some other logic (e.g. FFI currently produces code along the lines of |
Are we only looking into this for the purpose of reducing AOT code size? If so, then it seems to me the simplest solution would be to provide OS/Arch/... once we run global AOT transformations on the kernel. We wouldn't need to use any magic string override constants to do that. |
The goal is to reduce the code size of code that is compiled for production, which we simplified to mean AOT (on Native platforms) and |
Related SDK issue: dart-lang/sdk#31969 |
Discussion with @mkustermann and @mraleph earlier this week: With the addition of AbiSpecificIntegers (#42563), we also have our checking of whether the mapping contains the ABI that the VM is currently running on at kernel loading time, after the CFE. |
We have better options now than when this issue was posted. flutter/lib/src/foundation/constants.dart// Added July 2019
const bool kIsWeb = identical(0, 0.0);
// October 2022 onward
const bool kIsWeb = bool.fromEnvironment('dart.library.js_util');
Flutter now has Perhaps it's time to close the issue? |
That's not a |
Apparently tree-shaking for Still, making the variable a constant would be nice. |
Although it's not a const in source code, it is a constant when we compile for deployment. We added a special mechanism to make our compilers fold this away. So @pragma('vm:platform-const-if', !kDebugMode)
TargetPlatform get defaultTargetPlatform => platform.defaultTargetPlatform;
Not quite yet, as the |
Awesome, I did not know of this special mechanism. Thanks for the clarification @rrousselGit and @mkustermann! |
Still, there's significant value in marking it as const if possible. It's common for folks to do something like: bool isMyCustomFlag = something && defaultTargetPlatform == SomePlatform; But that flag can't be const because |
A problem is that the Compiling for multiple platforms is normal for modular compilation, where different parts of the program are compiled separately, then combined at the end, and sometimes a program can be compiled to a reusable intermediate form. (Kernel snapshot? I don't remember the name.) We can probably tell early on whether it's native compilation or not, with "not" currently meaning "web". With dart2wasm, I'm not sure there'll only be one "not native" in the future. That said, we allow |
That's what I was hoping personally: To have the Flutter tooling inject a --dart-define for the platform variable based in compilation target. |
Fwiw, everywhere modular compilation is supported by us we do not share kernel files across backend targets (compilers) anyways. So we can evaluate constants prior to linking, and some backends do evaluate constants prior to linking. One downside of course is we have to throw away the world when any global constants like this change. Clarification: by "modular compilation" I mean totally separate compilation to separate dill files which are later passed together to a backend (compiler). |
Currently there are few ways to check for the platform. They are mostly runtime and have downsides. Ways to check for different platforms are inconsistent.
kIsWeb
offlutter/foundation
is the most accepted way to check if the code is built for web. It translates toconst bool kIsWeb = identical(0, 0.0);
which is not future-proof. Who knows what other platforms Dart may support in the future that do not tell int from double?Platform.isAndroid
ofdart:io
which is not supported in web. These translate tostatic final bool isAndroid = (_operatingSystem == "android");
They take runtime comparison of strings which is not a first idea of efficiency when something is supposed to never change.A cleaner and faster solution would be to have one constant for a platform so it could be used in a
switch
so that a compiler could drop unneeded branches for every platform.Dart uses different compilers for different platforms, doesn't it? So it should be possible?
The text was updated successfully, but these errors were encountered: