diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 7e09bb3abe0..a5a107cf861 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -177,6 +177,7 @@ if (current_os == "win") { is_mac = false is_nacl = false is_posix = false + is_watchos = false is_win = true } else if (current_os == "mac") { is_android = false @@ -187,6 +188,7 @@ if (current_os == "win") { is_mac = true is_nacl = false is_posix = true + is_watchos = false is_win = false } else if (current_os == "android") { is_android = true @@ -197,6 +199,7 @@ if (current_os == "win") { is_mac = false is_nacl = false is_posix = true + is_watchos = false is_win = false } else if (current_os == "linux") { is_android = false @@ -207,6 +210,7 @@ if (current_os == "win") { is_mac = false is_nacl = false is_posix = true + is_watchos = false is_win = false } else if (current_os == "fuchsia") { is_android = false @@ -217,6 +221,7 @@ if (current_os == "win") { is_mac = false is_nacl = false is_posix = true + is_watchos = false is_win = false } else if (current_os == "ios") { is_android = false @@ -227,6 +232,23 @@ if (current_os == "win") { is_mac = false is_nacl = false is_posix = true + is_watchos = false + is_win = false +} else if (current_os == "watchos") { + is_android = false + is_chromeos = false + is_fuchsia = false + + # watchOS and iOS are similar enough, so almost all codepaths in + # BUILD files are the same for watchOS and iOS. Additionally, + # BUILD.gn zlib file doesn't support `is_watchos`, but works fine + # with `is_ios`. + is_ios = true + is_linux = false + is_mac = false + is_nacl = false + is_posix = true + is_watchos = true is_win = false } @@ -445,17 +467,19 @@ if (is_win) { host_toolchain = "//build/toolchain/mac:clang_$host_cpu" set_default_toolchain("//build/toolchain/mac:clang_$current_cpu") } else if (is_ios) { - import("//build/config/ios/ios_sdk.gni") # For use_ios_simulator + import("//build/config/ios/ios_sdk.gni") # For use_simulator host_toolchain = "//build/toolchain/mac:clang_$host_cpu" - if (use_ios_simulator) { - if (target_cpu == "arm64") { - set_default_toolchain("//build/toolchain/mac:ios_clang_arm64_sim") - } else { - set_default_toolchain("//build/toolchain/mac:ios_clang_x64_sim") - } + toolchain_target = "clang" + if (is_watchos) { + toolchain_target = "watchos_$toolchain_target" } else { - set_default_toolchain("//build/toolchain/mac:ios_clang_arm64") + toolchain_target = "ios_$toolchain_target" } + toolchain_target = "${toolchain_target}_$target_cpu" + if (use_simulator) { + toolchain_target = "${toolchain_target}_sim" + } + set_default_toolchain("//build/toolchain/mac:$toolchain_target") } else if (is_fuchsia) { assert(host_cpu == "x64") if (host_os == "linux") { @@ -554,7 +578,8 @@ if (!is_shared_library) { output_prefix = "lib" if (!defined(output_extension)) { - if (current_os == "mac" || current_os == "ios") { + if (current_os == "mac" || current_os == "ios" || + current_os == "watchos") { output_extension = "dylib" } else if (current_os == "win") { output_extension = "dll" diff --git a/build/config/ios/ios_sdk.gni b/build/config/ios/ios_sdk.gni index 4ee46a366e9..25eabedd514 100644 --- a/build/config/ios/ios_sdk.gni +++ b/build/config/ios/ios_sdk.gni @@ -6,28 +6,41 @@ import("//build/toolchain/rbe.gni") declare_args() { # SDK path to use. When empty this will use the default SDK based on the - # value of use_ios_simulator. + # value of use_simulator. ios_sdk_path = "" # Set to true when targeting a simulator build on iOS. False means that the # target is for running on the device. The default value is to use the # Simulator except when targeting GYP's Xcode builds (for compat with the # existing GYP build). - use_ios_simulator = false + use_simulator = false # Minimum supported version of the iOS SDK. ios_sdk_min = "12.0" + # Minimum supported version of the watchOS SDK. + watchos_sdk_min = "11.0" + # The path to the iOS device SDK. ios_device_sdk_path = "" # The path to the iOS simulator SDK. ios_simulator_sdk_path = "" + # The path to the watchOS device SDK. + watchos_device_sdk_path = "" + + # The path to the watchOS simulator SDK. + watchos_simulator_sdk_path = "" + ios_enable_relative_sdk_path = use_rbe } if (ios_sdk_path == "") { + if (is_watchos) { + ios_sdk_min = watchos_sdk_min + } + _find_sdk_args = [ "--print_sdk_path", ios_sdk_min, @@ -42,25 +55,44 @@ if (ios_sdk_path == "") { ] } - if (use_ios_simulator && ios_simulator_sdk_path == "") { - _find_sdk_args += [ "--platform=iphone_simulator" ] - _find_sdk_result = - exec_script("//build/mac/find_sdk.py", _find_sdk_args, "list lines") - ios_simulator_sdk_path = _find_sdk_result[0] + platform = "iphone" + if (is_watchos) { + platform = "watch" + } + if (use_simulator) { + platform = "${platform}_simulator" } - if (!use_ios_simulator && ios_device_sdk_path == "") { - _find_sdk_args += [ "--platform=iphone" ] - _find_sdk_result = - exec_script("//build/mac/find_sdk.py", _find_sdk_args, "list lines") - ios_device_sdk_path = _find_sdk_result[0] - } + _find_sdk_args += [ "--platform=$platform" ] + _find_sdk_result = + exec_script("//build/mac/find_sdk.py", _find_sdk_args, "list lines") + platform_sdk_path = _find_sdk_result[0] - if (use_ios_simulator) { - assert(ios_simulator_sdk_path != "") - ios_sdk_path = ios_simulator_sdk_path - } else { - assert(ios_device_sdk_path != "") - ios_sdk_path = ios_device_sdk_path + if (use_simulator && is_watchos) { + # watchos_simulator + if (watchos_simulator_sdk_path != "") { + platform_sdk_path = watchos_simulator_sdk_path + } + ios_sdk_path = platform_sdk_path + ios_sdk_min = watchos_sdk_min + } else if (!use_simulator && is_watchos) { + # watchos + if (watchos_device_sdk_path != "") { + platform_sdk_path = watchos_device_sdk_path + } + ios_sdk_path = platform_sdk_path + ios_sdk_min = watchos_sdk_min + } else if (use_simulator && !is_watchos) { + # ios_simulator + if (ios_simulator_sdk_path != "") { + platform_sdk_path = ios_simulator_sdk_path + } + ios_sdk_path = platform_sdk_path + } else if (!use_simulator && !is_watchos) { + # ios + if (ios_device_sdk_path != "") { + platform_sdk_path = ios_device_sdk_path + } + ios_sdk_path = platform_sdk_path } } diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn index 24f4755f51f..88ef256e37c 100644 --- a/build/toolchain/mac/BUILD.gn +++ b/build/toolchain/mac/BUILD.gn @@ -78,6 +78,55 @@ mac_toolchain_suite("ios_clang_x64_sim") { "-isysroot $ios_sdk_path -mios-simulator-version-min=$ios_sdk_min" } +if (is_watchos) { + # Toolchain used for watchOS device targets. + mac_toolchain_suite("watchos_clang_arm64") { + toolchain_cpu = "arm64" + toolchain_os = "watchos" + prefix = rebased_clang_dir + cc = "${compiler_prefix}${prefix}/clang" + cxx = "${compiler_prefix}${prefix}/clang++" + if (use_rbe) { + cc = "${cc} --target=arm64-apple-darwin" + cxx = "${cxx} --target=arm64-apple-darwin" + } + asm = "${assembler_prefix}${prefix}/clang" + ar = "${prefix}/llvm-ar" + ld = "${link_prefix}${prefix}/clang++" + strip = "${prefix}/llvm-strip" + nm = "${prefix}/llvm-nm" + is_clang = true + if (ios_enable_relative_sdk_path) { + ios_sdk_path = rebase_path(ios_sdk_path, root_build_dir) + } + sysroot_flags = "-isysroot $ios_sdk_path -mwatchos-version-min=$ios_sdk_min" + } + + # Toolchain used for watchOS simulator targets (arm64). + mac_toolchain_suite("watchos_clang_arm64_sim") { + toolchain_cpu = "arm64" + toolchain_os = "watchos" + prefix = rebased_clang_dir + cc = "${compiler_prefix}${prefix}/clang" + cxx = "${compiler_prefix}${prefix}/clang++" + if (use_rbe) { + cc = "${cc} --target=arm64-apple-darwin" + cxx = "${cxx} --target=arm64-apple-darwin" + } + asm = "${assembler_prefix}${prefix}/clang" + ar = "${prefix}/llvm-ar" + ld = "${link_prefix}${prefix}/clang++" + strip = "${prefix}/llvm-strip" + nm = "${prefix}/llvm-nm" + is_clang = true + if (ios_enable_relative_sdk_path) { + ios_sdk_path = rebase_path(ios_sdk_path, root_build_dir) + } + sysroot_flags = + "-isysroot $ios_sdk_path -mwatchos-simulator-version-min=$ios_sdk_min" + } +} + mac_toolchain_suite("clang_x64") { toolchain_cpu = "x64" toolchain_os = "mac" diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index d3d06a78b55..9db127b03c7 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -104,6 +104,14 @@ config("dart_os_config") { } else if (target_os == "ios") { defines += [ "DART_TARGET_OS_MACOS" ] defines += [ "DART_TARGET_OS_MACOS_IOS" ] + } else if (target_os == "watchos") { + defines += [ "DART_TARGET_OS_MACOS" ] + + # This doesn't look entirely correct, but so far it looks + # sufficient and allows to add watchOS support with less changes. + # If we need to differentiate iOS and watchOS targets later, we'll + # change this. + defines += [ "DART_TARGET_OS_MACOS_IOS" ] } else if (target_os == "linux") { defines += [ "DART_TARGET_OS_LINUX" ] } else if (target_os == "mac") { @@ -317,7 +325,10 @@ source_set("dart_api") { library_for_all_configs("libdart") { target_type = dart_component_kind - extra_nonproduct_deps = [ "vm:libprotozero" ] + extra_nonproduct_deps = [] + if (dart_support_perfetto) { + extra_nonproduct_deps += [ "vm:libprotozero" ] + } extra_deps = [ ":generate_version_cc_file", "../third_party/double-conversion/src:libdouble_conversion", diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc index 5f3c8a5f316..7ebcf63b085 100644 --- a/runtime/bin/process_macos.cc +++ b/runtime/bin/process_macos.cc @@ -903,6 +903,11 @@ int Process::Exec(Namespace* namespc, const char* working_directory, char* errmsg, intptr_t errmsg_len) { +#if defined(DART_HOST_OS_WATCH) + // execvp is not available on watchOS. + Utils::StrError(ENOSYS, errmsg, errmsg_len); + return -1; +#else if (working_directory != nullptr && TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { Utils::StrError(errno, errmsg, errmsg_len); @@ -912,6 +917,7 @@ int Process::Exec(Namespace* namespc, execvp(const_cast(path), const_cast(arguments)); Utils::StrError(errno, errmsg, errmsg_len); return -1; +#endif } static int SignalMap(intptr_t id) { diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h index 2996d476b08..00b22c133de 100644 --- a/runtime/platform/globals.h +++ b/runtime/platform/globals.h @@ -122,6 +122,9 @@ #if TARGET_OS_IPHONE #define DART_HOST_OS_IOS 1 #endif +#if TARGET_OS_WATCH +#define DART_HOST_OS_WATCH 1 +#endif #elif defined(_WIN32) diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni index 9ee225d137d..feebf8efc02 100644 --- a/runtime/runtime_args.gni +++ b/runtime/runtime_args.gni @@ -72,11 +72,14 @@ declare_args() { # Whether the sampling heap profiler should be included in product mode. dart_include_sampling_heap_profiler = false - # Whether features that depend on Perfetto should be built. We temporarily - # need to define this to allow excluding code that depends on Perfetto from - # being built on platforms which have a problem linking in the Perfetto - # library. - dart_support_perfetto = true + # Whether features that depend on Perfetto should be built. We need + # to define this to allow excluding code that depends on Perfetto + # from being built on platforms which have a problem linking in the + # Perfetto library, e.g. watchOS. + # + # is_watchos may be undefined when Dart SDK is built from the Flutter + # engine tree. + dart_support_perfetto = !defined(is_watchos) || !is_watchos # Whether to support dynamic loading and interpretation of Dart bytecode. dart_dynamic_modules = false diff --git a/runtime/tools/bin_to_assembly.py b/runtime/tools/bin_to_assembly.py index 6e3b373d823..888d2d7b329 100755 --- a/runtime/tools/bin_to_assembly.py +++ b/runtime/tools/bin_to_assembly.py @@ -51,7 +51,7 @@ def Main(): return -1 with open(options.output, "w") as output_file: - if options.target_os in ["mac", "ios"]: + if options.target_os in ["mac", "ios", "watchos"]: if options.executable: output_file.write(".text\n") else: @@ -106,7 +106,7 @@ def Main(): if incbin: output_file.write(".incbin \"%s\"\n" % options.input) - if options.target_os not in ["mac", "ios", "win", "win_gnu"]: + if options.target_os not in ["mac", "ios", "watchos", "win", "win_gnu"]: output_file.write(".size {0}, .-{0}\n".format(options.symbol_name)) if options.size_symbol_name: @@ -128,7 +128,7 @@ def Main(): else: output_file.write("dword %d\n" % size) else: - if options.target_os in ["mac", "ios"]: + if options.target_os in ["mac", "ios", "watchos"]: output_file.write( ".global _%s\n" % options.size_symbol_name) output_file.write("_%s:\n" % options.size_symbol_name) diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn index f4be2d999f9..19cfec7d866 100644 --- a/runtime/vm/BUILD.gn +++ b/runtime/vm/BUILD.gn @@ -172,7 +172,10 @@ source_set("libprotozero") { library_for_all_configs("libdart_vm") { target_type = "source_set" extra_product_deps = [] - extra_nonproduct_deps = [ ":libprotozero" ] + extra_nonproduct_deps = [] + if (dart_support_perfetto) { + extra_nonproduct_deps += [ ":libprotozero" ] + } extra_deps = [ "//third_party/icu:icui18n", "//third_party/icu:icuuc", @@ -213,7 +216,11 @@ library_for_all_configs_with_compiler("libdart_compiler") { public_configs = [ ":libdart_vm_config" ] sources = rebase_path(compiler_sources, ".", "./compiler/") include_dirs = [ ".." ] - extra_nonproduct_deps = [ ":libprotozero" ] + + extra_nonproduct_deps = [] + if (dart_support_perfetto) { + extra_nonproduct_deps += [ ":libprotozero" ] + } extra_deps = [] if (is_fuchsia) { extra_deps += [ "$fuchsia_sdk/pkg/trace-engine" ] @@ -222,7 +229,10 @@ library_for_all_configs_with_compiler("libdart_compiler") { library_for_all_configs("libdart_lib") { target_type = "source_set" - extra_nonproduct_deps = [ ":libprotozero" ] + extra_nonproduct_deps = [] + if (dart_support_perfetto) { + extra_nonproduct_deps += [ ":libprotozero" ] + } extra_deps = [] if (is_fuchsia) { extra_deps += [ "$fuchsia_sdk/pkg/trace-engine" ] diff --git a/runtime/vm/thread_interrupter_macos.cc b/runtime/vm/thread_interrupter_macos.cc index e9243a24973..0d07da01a09 100644 --- a/runtime/vm/thread_interrupter_macos.cc +++ b/runtime/vm/thread_interrupter_macos.cc @@ -49,7 +49,11 @@ class ThreadInterrupterMacOS { ASSERT(os_thread != nullptr); mach_thread_ = pthread_mach_thread_np(os_thread->id()); ASSERT(reinterpret_cast(mach_thread_) != nullptr); +#if !defined(DART_HOST_OS_WATCH) res = thread_suspend(mach_thread_); +#else + res = KERN_FAILURE; +#endif } void CollectSample() { @@ -58,9 +62,14 @@ class ThreadInterrupterMacOS { } auto count = static_cast(THREAD_STATE_FLAVOR_SIZE); thread_state_flavor_t state; +#if !defined(DART_HOST_OS_WATCH) kern_return_t res = thread_get_state(mach_thread_, THREAD_STATE_FLAVOR, reinterpret_cast(&state), &count); +#else + USE(count); + kern_return_t res = KERN_FAILURE; +#endif ASSERT(res == KERN_SUCCESS); Thread* thread = static_cast(os_thread_->thread()); if (thread == nullptr) { @@ -74,7 +83,11 @@ class ThreadInterrupterMacOS { if (res != KERN_SUCCESS) { return; } +#if !defined(DART_HOST_OS_WATCH) res = thread_resume(mach_thread_); +#else + res = KERN_FAILURE; +#endif ASSERT(res == KERN_SUCCESS); } diff --git a/tools/gn.py b/tools/gn.py index dcb48883b2e..752c6aa59d2 100755 --- a/tools/gn.py +++ b/tools/gn.py @@ -198,7 +198,12 @@ def ToGnArgs(args, mode, arch, target_os, sanitizer, verify_sdk_hash, gn_args['target_os'] = host_os elif target_os == 'ios_simulator': gn_args['target_os'] = 'ios' - gn_args['use_ios_simulator'] = True + gn_args['use_simulator'] = True + elif target_os == 'watchos_simulator': + gn_args['target_os'] = 'watchos' + gn_args['use_simulator'] = True + elif target_os == 'watchos': + gn_args['target_os'] = 'watchos' else: gn_args['target_os'] = target_os @@ -358,7 +363,7 @@ def ProcessOptions(args): for os_name in oses: if not os_name in [ 'android', 'freebsd', 'linux', 'macos', 'win32', 'fuchsia', - 'ios', 'ios_simulator' + 'ios', 'ios_simulator', 'watchos', 'watchos_simulator' ]: print("Unknown os %s" % os_name) return False @@ -393,7 +398,7 @@ def ProcessOptions(args): "Cross-compilation to %s is not supported for architecture %s." % (os_name, arch)) return False - elif os_name == 'ios' or os_name == 'ios_simulator': + elif os_name == 'ios' or os_name == 'ios_simulator' or os_name == 'watchos' or os_name == 'watchos_simulator': if not HOST_OS in ['macos']: print(f'Target os {os_name} is only supported on macOS') return False diff --git a/tools/utils.py b/tools/utils.py index d8d5200369e..b7686afdd81 100644 --- a/tools/utils.py +++ b/tools/utils.py @@ -339,6 +339,8 @@ def GetBuildConf(mode, arch, conf_os=None, sanitizer=None): os_fragment = conf_os.title() if (conf_os == 'ios_simulator'): os_fragment = 'IosSim' + if (conf_os == 'watchos_simulator'): + os_fragment = 'WatchosSim' return '{}{}{}'.format(GetBuildMode(mode), os_fragment, arch.upper()) # Ask for a cross build if the host and target architectures don't match. diff --git a/utils/aot_snapshot.gni b/utils/aot_snapshot.gni index 138e6baf011..032adeb3dbf 100644 --- a/utils/aot_snapshot.gni +++ b/utils/aot_snapshot.gni @@ -177,7 +177,7 @@ template("aot_snapshot") { output_prefix = "lib" output_extension = "" - if (current_os == "mac" || current_os == "ios") { + if (current_os == "mac" || current_os == "ios" || current_os == "watchos") { output_extension = "dylib" } else if (current_os == "win") { output_extension = "dll"