diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 00000000000..03f488b076a --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +5.3.0 diff --git a/README.md b/README.md index ffe0c850fe5..8183defb0e1 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ The config format may change in backwards-incompatible ways before `workerd` lea As of this writing, some major features are missing which we intend to fix shortly: -* **MacOS** is not supported yet, but should be imminently. We've never tried to build this code on Mac in the past, but we expect it should only require minor tweaks. Most of the work is figuring out how to wrangle the build system. (Windows users, meanwhile, should use WSL2. A native Windows port would be a challenge and is not currently being worked on.) * **Binary Packages** for various distributions are not built yet. We intend to provide these once out of beta. * **Wrangler/Miniflare integration** is in progress. The [Wrangler CLI tool](https://developers.cloudflare.com/workers/wrangler/) and [Miniflare](https://miniflare.dev/) will soon support local testing using `workerd` (replacing the previous simulated environment on top of Node). Wrangler should also support generating `workerd` configuration directly from a Wrangler project. * **Multi-threading** is not implemented. `workerd` runs in a single-threaded event loop. For now, to utilize multiple cores, we suggest running multiple instances of `workerd` and balancing load across them. We will likely add some built-in functionality for this in the near future. @@ -60,7 +59,7 @@ With that said, if you discover a bug that allows malicious code to break out of In theory, `workerd` should work on any POSIX system that is supported by V8. -In practice, `workerd` is tested on Linux (TODO: and MacOS) under x86-64 and arm64 architectures. +In practice, `workerd` is tested on Linux and macOS under x86-64 and arm64 architectures. On other platforms, you may have to do tinkering to make things work. Windows users should run `workerd` under WSL2. diff --git a/WORKSPACE b/WORKSPACE index 4520095d8b9..b5e56498bd9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -89,7 +89,7 @@ protobuf_deps() # workerd uses some Rust libraries, especially lolhtml for implementing HtmlRewriter. http_file( - name = "cargo_bazel", + name = "cargo_bazel_linux_x64", executable = True, sha256 = "a9f81a6fd356fc01e3da2483bdd1f9dfb080b0bdf5a128fa036c048e5b301562", urls = [ @@ -97,6 +97,24 @@ http_file( ], ) +http_file( + name = "cargo_bazel_macos_x64", + executable = True, + sha256 = "fb80acb9fcfd83674f73e98bf956bc65b33f31a4380ba72fbc1a6a9bf22c2f8c", + urls = [ + "https://github.com/bazelbuild/rules_rust/releases/download/0.10.0/cargo-bazel-x86_64-apple-darwin", + ], +) + +http_file( + name = "cargo_bazel_macos_arm64", + executable = True, + sha256 = "4104ea8edd3fccbcfc43265e4fa02dfc25b12b32250ff46456b829ab9cb78908", + urls = [ + "https://github.com/bazelbuild/rules_rust/releases/download/0.10.0/cargo-bazel-aarch64-apple-darwin", + ], +) + http_archive( name = "rules_rust", sha256 = "0cc7e6b39e492710b819e00d48f2210ae626b717a3ab96e048c43ab57e61d204", diff --git a/rust-deps/BUILD.bazel b/rust-deps/BUILD.bazel index dbb46cb6042..5c4e91b96e4 100644 --- a/rust-deps/BUILD.bazel +++ b/rust-deps/BUILD.bazel @@ -1,6 +1,34 @@ load("//:build/rust_cxx_bridge.bzl", "rust_cxx_bridge", "rust_cxx_include") load("@rules_rust//crate_universe:defs.bzl", "crate", "crates_vendor") load("@rules_rust//rust:defs.bzl", "rust_static_library") +load("@bazel_skylib//lib:selects.bzl", "selects") + +selects.config_setting_group( + name = "linux_x64", + match_all = [ + "@platforms//os:linux", + "@platforms//cpu:x86_64", + ], +) +selects.config_setting_group( + name = "macos_x64", + match_all = [ + "@platforms//os:macos", + "@platforms//cpu:x86_64", + ], +) +selects.config_setting_group( + name = "macos_arm64", + match_all = [ + "@platforms//os:macos", + "@platforms//cpu:aarch64", + ], +) +CARGO_BAZEL = select({ + "//:linux_x64": "@cargo_bazel_linux_x64//file:downloaded", + "//:macos_x64": "@cargo_bazel_macos_x64//file:downloaded", + "//:macos_arm64": "@cargo_bazel_macos_arm64//file:downloaded", +}) # TODO (before prod): # - arm64 build @@ -19,7 +47,7 @@ crates_vendor( shallow_since = "1657163695 -0400", )], }, - cargo_bazel = "@cargo_bazel//file:downloaded", + cargo_bazel = CARGO_BAZEL, mode = "remote", packages = { "anyhow": crate.spec( @@ -70,6 +98,7 @@ crates_vendor( }, supported_platform_triples = [ "x86_64-unknown-linux-gnu", + "aarch64-apple-darwin", # this is not used but its required to work around a bug in rules_rust where # invalid select statements can get generated in vendored BUILD files @@ -80,7 +109,7 @@ crates_vendor( # To repin crates: bazel run //rust-deps:cxxbridge_vendor -- --repin crates_vendor( name = "cxxbridge_vendor", - cargo_bazel = "@cargo_bazel//file:downloaded", + cargo_bazel = CARGO_BAZEL, mode = "remote", packages = { "cxxbridge-cmd": crate.spec( @@ -90,6 +119,7 @@ crates_vendor( # host toolchain only supported_platform_triples = [ "x86_64-unknown-linux-gnu", + "aarch64-apple-darwin", ], vendor_path = "cxxbridge_crates", ) diff --git a/rust-deps/crates/BUILD.ahash-0.7.6.bazel b/rust-deps/crates/BUILD.ahash-0.7.6.bazel index 3ae241d5f89..bf8a3268141 100644 --- a/rust-deps/crates/BUILD.ahash-0.7.6.bazel +++ b/rust-deps/crates/BUILD.ahash-0.7.6.bazel @@ -90,6 +90,7 @@ rust_library( ] + select_with_or({ # cfg(any(target_os = "linux", target_os = "android", target_os = "windows", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly", target_os = "solaris", target_os = "illumos", target_os = "fuchsia", target_os = "redox", target_os = "cloudabi", target_os = "haiku", target_os = "vxworks", target_os = "emscripten", target_os = "wasi")) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ # Target Deps @@ -100,6 +101,7 @@ rust_library( ], # cfg(not(all(target_arch = "arm", target_os = "none"))) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:wasm32-unknown-unknown", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ diff --git a/rust-deps/crates/BUILD.getrandom-0.1.16.bazel b/rust-deps/crates/BUILD.getrandom-0.1.16.bazel index 5bd6e856570..22d110a8710 100644 --- a/rust-deps/crates/BUILD.getrandom-0.1.16.bazel +++ b/rust-deps/crates/BUILD.getrandom-0.1.16.bazel @@ -96,6 +96,7 @@ rust_library( # # cfg(unix) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ # Target Deps diff --git a/rust-deps/crates/BUILD.getrandom-0.2.7.bazel b/rust-deps/crates/BUILD.getrandom-0.2.7.bazel index 12eaa85c196..3d52751e75b 100644 --- a/rust-deps/crates/BUILD.getrandom-0.2.7.bazel +++ b/rust-deps/crates/BUILD.getrandom-0.2.7.bazel @@ -91,6 +91,7 @@ rust_library( # # cfg(unix) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ # Target Deps diff --git a/rust-deps/crates/BUILD.rand-0.7.3.bazel b/rust-deps/crates/BUILD.rand-0.7.3.bazel index b93089c0b76..a8f4398cc9c 100644 --- a/rust-deps/crates/BUILD.rand-0.7.3.bazel +++ b/rust-deps/crates/BUILD.rand-0.7.3.bazel @@ -95,6 +95,7 @@ rust_library( ] + select_with_or({ # cfg(not(target_os = "emscripten")) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:wasm32-unknown-unknown", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ @@ -113,6 +114,7 @@ rust_library( # # cfg(unix) ( + "@rules_rust//rust/platform:aarch64-apple-darwin", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu", ): [ # Target Deps diff --git a/rust-deps/crates/defs.bzl b/rust-deps/crates/defs.bzl index 4a2f5f13e11..b9f165b6409 100644 --- a/rust-deps/crates/defs.bzl +++ b/rust-deps/crates/defs.bzl @@ -363,12 +363,12 @@ _BUILD_PROC_MACRO_ALIASES = { _CONDITIONS = { "cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))": ["wasm32-unknown-unknown"], - "cfg(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\"))": ["x86_64-unknown-linux-gnu"], - "cfg(not(all(target_arch = \"arm\", target_os = \"none\")))": ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"], - "cfg(not(target_os = \"emscripten\"))": ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"], + "cfg(any(target_os = \"linux\", target_os = \"android\", target_os = \"windows\", target_os = \"macos\", target_os = \"ios\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"dragonfly\", target_os = \"solaris\", target_os = \"illumos\", target_os = \"fuchsia\", target_os = \"redox\", target_os = \"cloudabi\", target_os = \"haiku\", target_os = \"vxworks\", target_os = \"emscripten\", target_os = \"wasi\"))": ["aarch64-apple-darwin", "x86_64-unknown-linux-gnu"], + "cfg(not(all(target_arch = \"arm\", target_os = \"none\")))": ["aarch64-apple-darwin", "wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"], + "cfg(not(target_os = \"emscripten\"))": ["aarch64-apple-darwin", "wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"], "cfg(target_os = \"emscripten\")": [], "cfg(target_os = \"wasi\")": [], - "cfg(unix)": ["x86_64-unknown-linux-gnu"], + "cfg(unix)": ["aarch64-apple-darwin", "x86_64-unknown-linux-gnu"], } ############################################################################### diff --git a/src/workerd/api/analytics-engine-impl.h b/src/workerd/api/analytics-engine-impl.h index d31af0fcd38..a06443fde40 100644 --- a/src/workerd/api/analytics-engine-impl.h +++ b/src/workerd/api/analytics-engine-impl.h @@ -8,6 +8,8 @@ namespace workerd::api { +using kj::uint; + constexpr uint MAX_INDEXES_LENGTH = 1; constexpr size_t MAX_INDEX_SIZE_IN_BYTES = 32; constexpr uint MAX_ARRAY_MEMBERS = 20; diff --git a/src/workerd/api/analytics-engine.h b/src/workerd/api/analytics-engine.h index ed32e75f3ad..b4f8feba5db 100644 --- a/src/workerd/api/analytics-engine.h +++ b/src/workerd/api/analytics-engine.h @@ -13,6 +13,7 @@ namespace workerd::api { using kj::byte; +using kj::uint; class AnalyticsEngine: public jsg::Object { // Analytics Engine is a tool for customers to get telemetry about anything diff --git a/src/workerd/api/r2-rpc.c++ b/src/workerd/api/r2-rpc.c++ index 56fb71caf8f..de234585182 100644 --- a/src/workerd/api/r2-rpc.c++ +++ b/src/workerd/api/r2-rpc.c++ @@ -170,7 +170,7 @@ kj::Promise doR2HTTPPutRequest(jsg::Lock& js, kj::Own } } } else { - expectedBodySize = 0ul; + expectedBodySize = uint64_t(0); KJ_REQUIRE(streamSize == nullptr); } diff --git a/src/workerd/api/streams/standard.h b/src/workerd/api/streams/standard.h index 5c5cb7f8723..7688ecd72c3 100644 --- a/src/workerd/api/streams/standard.h +++ b/src/workerd/api/streams/standard.h @@ -18,9 +18,9 @@ class WritableStreamDefaultController; class TransformStreamDefaultController; struct StreamQueuingStrategy { - using SizeAlgorithm = size_t(v8::Local); + using SizeAlgorithm = uint64_t(v8::Local); - jsg::Optional highWaterMark; + jsg::Optional highWaterMark; jsg::Optional> size; JSG_STRUCT(highWaterMark, size); diff --git a/src/workerd/api/url.h b/src/workerd/api/url.h index e4178db5e84..ad5dc5a63ea 100644 --- a/src/workerd/api/url.h +++ b/src/workerd/api/url.h @@ -11,6 +11,8 @@ namespace workerd::api { +using kj::uint; + class URLSearchParams; class URL: public jsg::Object { diff --git a/src/workerd/io/cdp.capnp b/src/workerd/io/cdp.capnp index 8d2e0223762..cf60cf9cf9b 100644 --- a/src/workerd/io/cdp.capnp +++ b/src/workerd/io/cdp.capnp @@ -13,7 +13,7 @@ $Cxx.namespace("workerd::cdp"); enum LogType { log @0; - debug @1; + debug @1 $Cxx.name("debug_"); # avoid collision with macro on Apple platforms info @2; error @3; warning @4; diff --git a/src/workerd/io/worker.c++ b/src/workerd/io/worker.c++ index ca8656f2616..c4af0d415e1 100644 --- a/src/workerd/io/worker.c++ +++ b/src/workerd/io/worker.c++ @@ -415,6 +415,17 @@ void reportStartupError( } } +uint64_t getCurrentThreadId() { +#if __linux__ + return syscall(SYS_gettid); +#else + // Assume MacOS or BSD + uint64_t tid; + pthread_threadid_np(NULL, &tid); + return tid; +#endif +} + } // namespace class Worker::InspectorClient: public v8_inspector::V8InspectorClient { @@ -430,7 +441,7 @@ public: auto& ioContext = IoContext::current(); timePoint = ioContext.now(); } else KJ_IF_MAYBE(info, inspectorTimerInfo) { - if (info->threadId == syscall(SYS_gettid)) { + if (info->threadId == getCurrentThreadId()) { // We're on an inspector-serving thread. timePoint = info->timer.now() + info->timerOffset - kj::origin() + kj::UNIX_EPOCH; @@ -448,14 +459,14 @@ public: void setInspectorTimerInfo(kj::Timer& timer, kj::Duration timerOffset) { // Helper for attachInspector(). - inspectorTimerInfo = InspectorTimerInfo { timer, timerOffset, syscall(SYS_gettid) }; + inspectorTimerInfo = InspectorTimerInfo { timer, timerOffset, getCurrentThreadId() }; } private: struct InspectorTimerInfo { kj::Timer& timer; kj::Duration timerOffset; - long threadId; + uint64_t threadId; }; kj::Maybe inspectorTimerInfo; diff --git a/src/workerd/jsg/setup.c++ b/src/workerd/jsg/setup.c++ index d8989975a7a..4f14c4675dc 100644 --- a/src/workerd/jsg/setup.c++ +++ b/src/workerd/jsg/setup.c++ @@ -2,6 +2,11 @@ // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 +#if __APPLE__ +// We need to define `_XOPEN_SOURCE` to get `ucontext_t` on Mac. +#define _XOPEN_SOURCE +#endif + #include "setup.h" #include #include "libplatform/libplatform.h" @@ -12,6 +17,10 @@ #include #endif +#if defined(__APPLE__) && defined(__aarch64__) +#include +#endif + namespace workerd::jsg { static bool v8Initialized = false; @@ -542,11 +551,19 @@ kj::Maybe getJsStackTrace(void* ucontext, kj::ArrayPtr scra v8::RegisterState state; auto& mcontext = reinterpret_cast(ucontext)->uc_mcontext; -#if __x86_64__ +#if defined(__APPLE__) && defined(__x86_64__) + state.pc = reinterpret_cast(mcontext->__ss.__rip); + state.sp = reinterpret_cast(mcontext->__ss.__rsp); + state.fp = reinterpret_cast(mcontext->__ss.__rbp); +#elif defined(__APPLE__) && defined(__aarch64__) + state.pc = reinterpret_cast(arm_thread_state64_get_pc(mcontext->__ss)); + state.sp = reinterpret_cast(arm_thread_state64_get_sp(mcontext->__ss)); + state.fp = reinterpret_cast(arm_thread_state64_get_fp(mcontext->__ss)); +#elif defined(__linux__) && defined(__x86_64__) state.pc = reinterpret_cast(mcontext.gregs[REG_RIP]); state.sp = reinterpret_cast(mcontext.gregs[REG_RSP]); state.fp = reinterpret_cast(mcontext.gregs[REG_RBP]); -#elif __aarch64__ +#elif defined(__linux__) && defined(__aarch64__) state.pc = reinterpret_cast(mcontext.pc); state.sp = reinterpret_cast(mcontext.sp); state.fp = reinterpret_cast(mcontext.regs[29]); diff --git a/src/workerd/jsg/util.c++ b/src/workerd/jsg/util.c++ index 54354ce0e94..36c8d3b239e 100644 --- a/src/workerd/jsg/util.c++ +++ b/src/workerd/jsg/util.c++ @@ -6,7 +6,7 @@ #include "setup.h" #include #include -#include +#include #include diff --git a/src/workerd/jsg/wrappable.h b/src/workerd/jsg/wrappable.h index a442197071b..54e6353d90f 100644 --- a/src/workerd/jsg/wrappable.h +++ b/src/workerd/jsg/wrappable.h @@ -17,6 +17,8 @@ namespace workerd::jsg { +using kj::uint; + class GcVisitor; class HeapTracer; diff --git a/src/workerd/server/server.h b/src/workerd/server/server.h index 63a40bb71f9..806cfa925b7 100644 --- a/src/workerd/server/server.h +++ b/src/workerd/server/server.h @@ -21,6 +21,8 @@ namespace workerd::jsg { namespace workerd::server { +using kj::uint; + class Server: private kj::TaskSet::ErrorHandler { // Implements the single-tenant Workers Runtime server / CLI. // diff --git a/src/workerd/server/workerd.c++ b/src/workerd/server/workerd.c++ index 97289dcd5f9..016fddd8009 100644 --- a/src/workerd/server/workerd.c++ +++ b/src/workerd/server/workerd.c++ @@ -32,6 +32,12 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#define environ (*_NSGetEnviron()) +#endif + namespace workerd::server { static kj::StringPtr getVersionString() { @@ -885,7 +891,16 @@ private: } #endif - // TODO(launch): Fall back to searching $PATH. Or on Mac, maybe use _NSGetExecutablePath()? + #if __APPLE__ + // https://astojanov.github.io/blog/2011/09/26/pid-to-absolute-path.html + pid_t pid = getpid(); + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + if (proc_pidpath(pid, pathbuf, sizeof(pathbuf)) > 0) { + return tryOpenExe(pathbuf); + } + #endif + + // TODO(launch): Fall back to searching $PATH. return nullptr; }