From e534983216e6db5fdc8bd7c773c3a6a5a519301a Mon Sep 17 00:00:00 2001 From: Ivan Inozemtsev Date: Mon, 3 Feb 2025 23:31:21 -0800 Subject: [PATCH] Linkable AOT snapshots on macOS Update `aot_snapshot` template to optionally build a shared library from `app-aot-assembly` sanpshot. Change-Id: Ifb7cee65b5699099fa676312fff7d687cfb52d98 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/407060 Reviewed-by: Ryan Macnak Commit-Queue: Ivan Inozemtsev --- BUILD.gn | 8 +- samples/embedder/BUILD.gn | 8 ++ tests/standalone/embedder_samples_test.dart | 2 +- utils/aot_snapshot.gni | 104 +++++++++++++++++--- 4 files changed, 100 insertions(+), 22 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 7af5c7945d1..3e889cdad4f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -29,14 +29,9 @@ group("most") { ":dartanalyzer", ":ddc", ":runtime", - ":samples", ] } -group("samples") { - deps = [ "samples/embedder:all" ] -} - group("runtime") { import("runtime/runtime_args.gni") @@ -69,7 +64,8 @@ group("runtime") { # AOT samples use dlopen to load AOT snapshots and it works only on # 64-bit Linux right now. - if (is_linux && (dart_target_arch == "x64" || dart_target_arch == "arm64")) { + if ((is_linux || is_mac) && + (dart_target_arch == "x64" || dart_target_arch == "arm64")) { deps += [ "samples/embedder:aot" ] } diff --git a/samples/embedder/BUILD.gn b/samples/embedder/BUILD.gn index f6a51c4a381..cf132301b2c 100644 --- a/samples/embedder/BUILD.gn +++ b/samples/embedder/BUILD.gn @@ -99,6 +99,14 @@ template("snapshots") { # AOT snapshot aot_snapshot("${target_name}_aot") { main_dart = invoker.main_dart + + # AOT snapshots as shared libraries on Windows are not + # supported, and in fact we don't build AOT samples on + # Windows. However, GN evaluation model will still + # evaluate the `aot_snapshot` template on Windows, + # and it will fail the assert if as_shared_library is + # true, and the current platform is Windows. + as_shared_library = !is_win } } diff --git a/tests/standalone/embedder_samples_test.dart b/tests/standalone/embedder_samples_test.dart index 71e56a5a0c8..cce802c113c 100644 --- a/tests/standalone/embedder_samples_test.dart +++ b/tests/standalone/embedder_samples_test.dart @@ -32,7 +32,7 @@ void checkSample( } void main() { - final executable = Platform.executable; + final executable = File(Platform.executable).absolute.path; final out = executable.substring(0, executable.lastIndexOf('dart') - 1); checkSample('$out/run_main_kernel', ['$out/gen/hello_kernel.dart.snapshot']); diff --git a/utils/aot_snapshot.gni b/utils/aot_snapshot.gni index 731fe4c2ac8..e799793c53c 100644 --- a/utils/aot_snapshot.gni +++ b/utils/aot_snapshot.gni @@ -100,27 +100,101 @@ template("aot_snapshot") { } } - # Create a snapshot from kernel built above. - gen_snapshot_action(target_name) { - if (defined(invoker.pool)) { - pool = invoker.pool + # Whether to build an AOT snapshot, which can be opened by dlopen. + # Ignore this option on Linux, as the default app-aot-elf AOT + # snapshot already can be used with dlopen on Linux. + as_shared_library = defined(invoker.as_shared_library) && + invoker.as_shared_library && !is_linux + + assert(!(as_shared_library && is_win), + "AOT Snapshots as shared libraries are not supported on Windows") + + if (!as_shared_library) { + # Create a snapshot from kernel built above. + gen_snapshot_action(target_name) { + if (defined(invoker.pool)) { + pool = invoker.pool + } + deps = extra_deps + [ ":${target_name}_dill" ] + + inputs = extra_inputs + + outputs = [ output ] + + abs_output = rebase_path(output) + + vm_args = [ + "--deterministic", + "--snapshot-kind=app-aot-elf", + "--elf=$abs_output", + ] + gen_snapshot_args + + args = [ rebase_path(dill) ] + + force_product_mode = product_mode } - deps = extra_deps + [ ":${target_name}_dill" ] + } else { + assembly = "$target_gen_dir/$name.S" + dill_target_name = ":${target_name}_dill" - inputs = extra_inputs + # Create an assembly snapshot from kernel built above. + assembly_target_name = target_name + "_assembly" + gen_snapshot_action(assembly_target_name) { + if (defined(invoker.pool)) { + pool = invoker.pool + } + deps = extra_deps + [ dill_target_name ] - outputs = [ output ] + inputs = extra_inputs - abs_output = rebase_path(output) + outputs = [ assembly ] - vm_args = [ - "--deterministic", - "--snapshot-kind=app-aot-elf", - "--elf=$abs_output", - ] + gen_snapshot_args + abs_output = rebase_path(assembly) + vm_args = [ + "--deterministic", + "--snapshot-kind=app-aot-assembly", + "--assembly=$abs_output", + ] + gen_snapshot_args - args = [ rebase_path(dill) ] + args = [ rebase_path(dill) ] - force_product_mode = product_mode + force_product_mode = product_mode + } + + # build a shared library from assembly. + shared_library_target_name = target_name + "_shared_library" + shared_library(shared_library_target_name) { + sources = [ assembly ] + deps = [ ":${assembly_target_name}" ] + } + + output_prefix = "lib" + output_extension = "" + + if (current_os == "mac" || current_os == "ios") { + output_extension = "dylib" + } else if (current_os == "win") { + output_extension = "dll" + output_prefix = "" + } else if (current_os == "unknown" && current_cpu == "wasm32") { + output_extension = "wasm" + } else { + output_extension = "so" + } + + shared_library_output_file_name = + "$output_prefix$shared_library_target_name" + if (output_extension != "") { + shared_library_output_file_name += ".$output_extension" + } + + # copy shared library to the same output, as when + # `as_shared_library` is False. + copy(target_name) { + sources = [ "$root_out_dir/$shared_library_output_file_name" ] + outputs = [ output ] + + deps = [ ":${shared_library_target_name}" ] + } } }