-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Allow AOT executables to be cross-compiled #28617
Comments
Might as well give some subset of our users a speed-up while we wait for dart-lang/sdk#28617.
Might as well give some subset of our users a speed-up while we wait for dart-lang/sdk#28617.
App snapshots are tied to the target ABI of the VM, not the host OS and not the host ABI. If you create an app snapshot using an IA32 VM, you can run the same snapshot on Windows, Mac or Linux. If you create an app snapshot using an X64 VM on Mac or Linux, you run it on the other (they share the sysv ABI), but not Windows (which has its own ABI). If you create an app snapshot using a SIMARM VM on your desktop, you can run it with an ARM VM on, say, an Android device (this is how Flutter works). We will not produce VMs that target multiple ABIs. The assumption of a single target ABI as a build-time decision is quite deep in the VM. |
I want to push back strongly on this. Startup performance is very important for providing my users with a good experience, and the Dart VM's startup performance without using application snapshots compares poorly to just about any other language (including Ruby, whose Sass implementation we're in the process of deprecating because of performance issues). Other languages are able to do this. Easy cross-compilation is a major reason that Go is so popular for writing command-line tools, and if Dart provided it with similar ease it would make the server-side Dart world very compelling. But without it, Dart users are forced to deal with sub-par performance when they could easily get performance and portability with another language. |
Ping... efficient startup speeds across all platforms are a very important customer feature. |
I haven't received any response, so I'm re-opening this. It's a pressing customer issue. |
One workaround is https://github.com/filiph/dartbin which creates a go wrapper. Not Dart2 compatible though and it requires go as dependency. |
Updating to AOT executables, since that's not the best way to distribute CLI applications. |
@mit-mit has told me offline that "getting to full cross-compilation is going to be a long journey", but "the journey has already started; we just don't have a timeline for when it will end". |
Looking forward to see this feature! Loving to work with dart ❤ |
This feature is a show stopper for us in order to adopt Dart in AWS Lambda. Since the AWS CLI runs the compiled executable in a Docker container, offline development is only possible in a Linux environment. Manual deployment without CI/CD is also impossible in Mac and Windows. |
Also a cross-compile option for linux ARM architectures please! |
Potential work-around that may work for some: https://blog.dantup.com/2019/11/easily-compiling-dart-to-native-executables-for-windows-linux-macos-with-github-actions/ |
Just found this wiki: https://github.com/dart-lang/sdk/wiki/Building-Dart-SDK-for-ARM-processors#building I wonder if |
Ah, that would be awesome to have a cross compilation ! I'm trying to use Dart for several projects for Raspberry, but that's hard to easily win this battle without ability to get ARM binary using my host OS (MacOS). What's about plan? Will this feature be included once? |
Is there an update to this? Really interested in cross-compilation! |
Would something like this be an interesting mid-term solution?
|
That's pretty close to how it would be implemented in the long term too (if we had resources or if we had somebody willing to contribute external implementation). Few missing pieces to take it all the way:
|
If I understand correctly the |
@dvc94ch Note that The root of this is in Dart's origins. Dart is originally a JITed language and JITs tend to have host == target. Additionally there is a tight coupling between compilation toolchain and the runtime system (again because it was first and foremost a JITed language). So most of the code was written like that and properly disentangling this is quite an adventure. We managed to disentangle some of it when we were forced to support generating 32-bit ARM code on 64-bit hosts (due to Mac OS X removing support for 32-bit binaries), but there are still more things to refactor. |
I used this GitHub action workflow to get cross-platform builds
and here is the result |
I think people are more concerned with cross compiling debug builds on a development machine and testing it on a target machine than creating cross compiled releases. There are a few reasons why it's hard even if dart could cross compile or why it's not a great idea.
It is already possible today by using the kernel_blob.bin (cross compiled windows apps work already) and I'm working on a tool that exposes this (among other things like packaging, signing and publishing) to flutter developers. |
Is there any way to build the aot assembly for iOS from Linux/windows? kernel_blob.bin won't work on iOS right? Got other platforms working, still figuring out iOS. |
So https://github.com/cloudpeers/xbuild would really benefit from being able to create aot snapshots for ios from linux/windows. It's the only reason you still need a mac for developing ios apps on non jailbroken ios devices. Of course you still need an apple developer subscription. |
|
Coming back to this because it occurred to me to ask: how does Flutter already manage to do this? Flutter is able to both:
In both the above, my assumption is that cross compilation is happening for the Flutter apps Dart code and if so is this all Flutter specific code and is there a reason it cannot be used for Dart cli as well as Flutter apps? My current use case for cross compiling is trying to develop for a RISC-V device where the CPU is relatively slow and also has a modest (512MB) amount of RAM so running Dart on the cli (which of course requires compiling) is very slow and so on device development is very slow and painful. |
@maks Flutter does it in the same way which is described in #28617 (comment) and other comments on the thread. They build a bunch of Dart's |
Thanks @mraleph 👍🏻 that gives me a good place to go start looking into the Flutter code to learn how they build the separate In regards to the packaging and distribution for doing this in Dart, is there the possibility of reusing the infrastructure that Flutter has setup or do the Dart & Flutter projects prefer to keep these separate? |
You will have to read their buildbot recipes for that (https://flutter.googlesource.com/recipes). It's all done on the CI and uploaded to the cloud storage bucket. Ultimately it is just about configuring the engine build with the right flags.
We will probably have some variation of the same infrastructure. We had a brief chat with @mit-mit and we might lay some ground work for this next quarter. |
I think "dart can't cross compile" is simply a lie !!! Because apparently, flutter can compile an arm apk file directly on window, linux amd64 machine. |
With Mac moving over to arm. Being able to cross-compile because even more important. Because people on mac will not be able to run a windows vm and do the compiling there. So we will need 2 seperated machines now just to get our executables for all platforms... But I'll need to ask then: Why does the dart compile command mention the --target-os option to begin with? Why does it not print a warning that --target-os is currently ignored when entered? |
With MacOS having two different architectures arm and intell I need to have two Mac machines to compile all the variants. Note that not all CI platforms, as GitHub offer Arm Mac machines. So you would need to search to cover your Mac compilation needs. |
Upstreamed changes from cl/579854752. The cross-compiler checks some things that are check on Windows. * Correct capitalization of filenames in includes. * Field initialization order in constructors. In the cross compilation process, some binaries are run on the host. This unveiled missing `UnwindingRecords::GenerateRecordsInto`. Finally, when emitting blob data with a symbol in assembly, the `.type` directive is not supported but the format should still be unix style assemble. So this CL introduces "win_gnu". This tool is directly invoked from the build-rules in cl/579854752, and will not be used until we address #28617. TEST=windows bots Change-Id: I94256589e8c231b45b8e14a63727c782416c2e98 Cq-Include-Trybots: luci.dart.try:vm-aot-win-debug-arm64-try,vm-aot-win-debug-x64c-try,pkg-win-release-try,pkg-win-release-arm64-try,vm-win-debug-arm64-try,vm-win-debug-x64c-try,vm-win-debug-x64-try,vm-msvc-windows-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/335520 Commit-Queue: Daco Harkes <dacoharkes@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
Alternative approach Using node.js to create executablesI have a work around that I would like to share as it does not require any GitHub services, etc. It can all be done from command line. I am compiling to JS, then using node.js tools to convert to executable. I wrote a bash script to simplify the process. This is certainly not going to be the most efficient and probably has gaps (that I haven't found), but for the command line tools I've been building it has worked well so far. Until it is supported natively... Example StepsCreate the js filesdart compile js bin/hello.dart -o js/hello.js Command line arguments don’t work in generated jsIt turns out that for some reason the command line arguments passed to the program are not picked up by the generated node program, unless you do a special little trick. I found out about the trick from this site: https://japhr.blogspot.com/2014/07/command-line-arguments-with-nodejs-and.html Basically the trick is to add a function to the generated node.js file: function dartMainRunner(main, args) {
main(process.argv.slice(2));
} Create the executable using node.js toolsCreate the package.json file in js directory{
"name": "hello",
"version": "0.0.1",
"description": "Say hello.",
"main": "hello.js",
"bin": "hello.js",
"author": "anybody",
"license": "MIT"
} Then build the executablepkg . Script to do all of thisIn order to automate this I created a script dart2js in ~/local/bin that does all of these steps. #!/bin/bash
if [[ "$1" == "" ]]; then
echo -e "Usage:\n\t$0 [basename]"
exit 1
fi
if [[ ! -f bin/$1.dart ]]; then
echo "bin/$1.dart does not exist"
exit 2
fi
dart compile js bin/$1.dart -o js/$1.js
if [ $? -ne 0 ]; then
echo "Compiling js failed, exiting build script"
exit 3
fi
wrapper='function dartMainRunner(main, args) { main(process.argv.slice(2)); }';
echo $wrapper >> js/$1.js
cat <<EOT > js/package.json
{
"name": "$1",
"version": "0.0.1",
"description": "Do amazing $1 stuff.",
"main": "$1.js",
"bin": "$1.js",
"author": "Geoff Ruscoe",
"license": "MIT"
}
EOT
cd js
pkg . |
this method produces much big sized binary. For simple hello world example, the binary maybe almost 100MB. I would prefer to use github action using matrix to build the aot binary. |
Currently application snapshots (as described here) can only be compiled for the architecture of the machine doing the compilation. This makes releasing cross-platform apps using these snapshots much more difficult, requiring multiple machines (including at least one physical machine, since OS X isn't virtualizable) to compile for all platforms.
It seems that the compilation process could do the initial run on the current platform, but then preserve the profiling information and use it to cross-compile the result to other platforms.
The text was updated successfully, but these errors were encountered: