Bug 1490948: Add build system support for a Rust library in Spidermonkey; r=chmanchester
authorBenjamin Bouvier <benj@benj.me>
Tue, 25 Sep 2018 15:56:56 +0200
changeset 438649 537457dc2f47fa9436c5abb6b27977ae9727e059
parent 438648 66a1434be89e0345e70f585fd2a960dae41324ce
child 438650 2225cbe1f042a75fc02177dd4daa86c3208997d7
push id108365
push userbbouvier@mozilla.com
push dateFri, 28 Sep 2018 07:14:31 +0000
treeherdermozilla-inbound@2aec59694789 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschmanchester
bugs1490948
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1490948: Add build system support for a Rust library in Spidermonkey; r=chmanchester This introduces two new crates: - jsrust, for standalone builds. This crate is compiled into a static library libjsrust.a, which gets linked into the shared Spidermonkey library when it's built, or into the static Spidermonkey library otherwise. This is just a static library wrapping jsrust_shared below. - jsrust_shared, for Gecko embedding. It just references other Rust crates actively used in Spidermonkey. It is used to be embedded as part of a new Rust dependency in Gecko (in gkrust).
Cargo.toml
js/src/fuzz-tests/moz.build
js/src/gdb/moz.build
js/src/jsapi-tests/moz.build
js/src/moz.build
js/src/rust/Cargo.toml
js/src/rust/lib.rs
js/src/rust/moz.build
js/src/rust/shared/Cargo.toml
js/src/rust/shared/lib.rs
js/src/shell/moz.build
js/src/wasm/cranelift/Cargo.toml
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/mach_commands.py
toolkit/library/gtest/rust/Cargo.toml
toolkit/library/rust/Cargo.toml
toolkit/library/rust/gkrust-features.mozbuild
toolkit/library/rust/shared/Cargo.toml
toolkit/library/rust/shared/lib.rs
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,16 +1,18 @@
 [workspace]
 
 # These are the "root" crates, which we build and test as top-level targets.
 # Their transitive dependencies and dev-dependencies are included automatically
 # and do not need to be listed here. Their external dependencies are vendored
 # into `third_party/rust` by `mach vendor rust`.
 members = [
   "js/src",
+  "js/src/rust",
+  "js/src/wasm/cranelift",
   "js/rust",
   "js/src/frontend/binsource", # Code generator.
   "testing/geckodriver",
   "toolkit/crashreporter/rust",
   "toolkit/library/gtest/rust",
   "toolkit/library/rust/",
 ]
 
--- a/js/src/fuzz-tests/moz.build
+++ b/js/src/fuzz-tests/moz.build
@@ -38,14 +38,19 @@ if CONFIG['LIBFUZZER']:
 
     # Add libFuzzer configuration directives
     include('/tools/fuzzing/libfuzzer-config.mozbuild')
 
 USE_LIBS += [
     'static:js',
 ]
 
+if CONFIG['ENABLE_WASM_CRANELIFT']:
+    USE_LIBS += [
+        'jsrust'
+    ]
+
 if CONFIG['MOZ_NEEDS_LIBATOMIC']:
     OS_LIBS += ['atomic']
 
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
 DEFINES['topsrcdir'] = '%s/js/src' % TOPSRCDIR
--- a/js/src/gdb/moz.build
+++ b/js/src/gdb/moz.build
@@ -36,13 +36,18 @@ LOCAL_INCLUDES += [
     '!..',
     '..',
 ]
 
 USE_LIBS += [
     'static:js',
 ]
 
+if CONFIG['ENABLE_WASM_CRANELIFT']:
+    USE_LIBS += [
+        'jsrust'
+    ]
+
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
 DEFINES['topsrcdir'] = '%s/js/src' % TOPSRCDIR
 FINAL_TARGET_PP_FILES += ['gdb-tests-gdb.py.in']
 OBJDIR_FILES.js.src.gdb += ['!/dist/bin/gdb-tests-gdb.py']
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -160,15 +160,20 @@ LOCAL_INCLUDES += [
     '!..',
     '..',
 ]
 
 USE_LIBS += [
     'static:js',
 ]
 
+if CONFIG['ENABLE_WASM_CRANELIFT']:
+    USE_LIBS += [
+        'jsrust'
+    ]
+
 if CONFIG['MOZ_NEEDS_LIBATOMIC']:
     OS_LIBS += ['atomic']
 
 OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
 DEFINES['topsrcdir'] = '%s/js/src' % TOPSRCDIR
 OBJDIR_PP_FILES.js.src['jsapi-tests'] += ['jsapi-tests-gdb.py.in']
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -38,17 +38,16 @@ for gcfile in ['devtools/rootAnalysis', 
 
 for stlfile in ['jsdate.*', 'jsnum.*']:
     with Files(stlfile):
         BUG_COMPONENT = component_stl
 
 with Files('builtin/intl/*'):
     BUG_COMPONENT = component_intl
 
-
 if CONFIG['JS_BUNDLED_EDITLINE']:
     DIRS += ['editline']
 
 if not CONFIG['JS_DISABLE_SHELL']:
     DIRS += ['shell']
 
 TEST_DIRS += ['jsapi-tests', 'tests', 'gdb']
 
@@ -697,16 +696,22 @@ ReservedWordsGenerated.inputs += [
 ]
 
 DIRS += [
     'build',
 ]
 
 FINAL_LIBRARY = 'js'
 
+if CONFIG['ENABLE_WASM_CRANELIFT']:
+    DIRS += ['rust']
+    UNIFIED_SOURCES += [
+        'wasm/WasmCraneliftCompile.cpp',
+    ]
+
 if CONFIG['JS_BUILD_BINAST']:
     # Using SOURCES, as UNIFIED_SOURCES causes mysterious bugs on 32-bit platforms.
     # These parts of BinAST are designed only to test evolutions of the
     # specification.
     SOURCES += ['frontend/BinTokenReaderTester.cpp']
     # These parts of BinAST should eventually move to release.
     SOURCES += [
         'frontend/BinSource-auto.cpp',
copy from js/src/wasm/cranelift/Cargo.toml
copy to js/src/rust/Cargo.toml
--- a/js/src/wasm/cranelift/Cargo.toml
+++ b/js/src/rust/Cargo.toml
@@ -1,22 +1,12 @@
 [package]
-name = "baldrdash"
+name = "jsrust"
 version = "0.1.0"
-authors = ["The Spidermonkey and Cranelift developers"]
+authors = ["The Spidermonkey developers"]
 
 [lib]
+name = "jsrust"
 crate-type = ["staticlib"]
-name = "baldrdash"
+path = "lib.rs"
 
 [dependencies]
-cranelift-codegen = "0.20.0"
-cranelift-wasm = "0.20.1"
-target-lexicon = "0.0.3"
-log = { version = "0.4.4", default-features = false, features = ["release_max_level_warn"] }
-env_logger = "0.5.6"
-
-[build-dependencies]
-bindgen = {version = "0.39", default-features = false} # disable `logging` to reduce code size
-
-# Uncomment this to enable perf support in release mode.
-#[profile.release]
-#debug = true
+jsrust_shared = { path = "./shared" }
new file mode 100644
--- /dev/null
+++ b/js/src/rust/lib.rs
@@ -0,0 +1,15 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+extern crate jsrust_shared;
new file mode 100644
--- /dev/null
+++ b/js/src/rust/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+RustLibrary('jsrust')
+
+if CONFIG['JS_SHARED_LIBRARY']:
+    FINAL_LIBRARY = 'js'
+
+if CONFIG['OS_ARCH'] == 'Darwin':
+    # The Rust standard library references libresolv on macOS, so we need to
+    # link it as a workaround. See also bug 1367932.
+    OS_LIBS += ['-lresolv']
+elif CONFIG['OS_ARCH'] == 'WINNT':
+    # Extra libraries used by Rust bindings libs in debug builds.
+    OS_LIBS += [
+        'shell32',
+        'userenv',
+        'ws2_32',
+    ]
new file mode 100644
--- /dev/null
+++ b/js/src/rust/shared/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "jsrust_shared"
+version = "0.1.0"
+authors = ["The Spidermonkey developers"]
+
+[lib]
+crate-type = ["rlib"]
+name = "jsrust_shared"
+path = "lib.rs"
+
+[dependencies]
+baldrdash = { path = "../../wasm/cranelift" }
+
+[build-dependencies]
+bindgen = {version = "0.39", default-features = false} # disable `logging` to reduce code size
+
+# Uncomment this to enable perf support in release mode.
+#[profile.release]
+#debug = true
new file mode 100644
--- /dev/null
+++ b/js/src/rust/shared/lib.rs
@@ -0,0 +1,15 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+extern crate baldrdash;
--- a/js/src/shell/moz.build
+++ b/js/src/shell/moz.build
@@ -4,16 +4,20 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['JS_SHELL_NAME']:
     GeckoProgram(CONFIG['JS_SHELL_NAME'], linkage=None)
     if CONFIG['JS_BUNDLED_EDITLINE']:
         USE_LIBS += ['editline']
     USE_LIBS += ['static:js']
+    if CONFIG['ENABLE_WASM_CRANELIFT']:
+        USE_LIBS += [
+            'jsrust'
+        ]
 
 include('../js-config.mozbuild')
 include('../js-cxxflags.mozbuild')
 
 UNIFIED_SOURCES += [
     'js.cpp',
     'jsoptparse.cpp',
     'jsshell.cpp',
--- a/js/src/wasm/cranelift/Cargo.toml
+++ b/js/src/wasm/cranelift/Cargo.toml
@@ -1,15 +1,15 @@
 [package]
 name = "baldrdash"
 version = "0.1.0"
 authors = ["The Spidermonkey and Cranelift developers"]
 
 [lib]
-crate-type = ["staticlib"]
+crate-type = ["rlib"]
 name = "baldrdash"
 
 [dependencies]
 cranelift-codegen = "0.20.0"
 cranelift-wasm = "0.20.1"
 target-lexicon = "0.0.3"
 log = { version = "0.4.4", default-features = false, features = ["release_max_level_warn"] }
 env_logger = "0.5.6"
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1467,16 +1467,19 @@ class RecursiveMakeBackend(CommonBackend
         assert len(direct_linked) == 1
 
         # TODO: see bug 1310063 for checking dependencies are set up correctly.
 
         direct_linked = direct_linked[0]
         backend_file.write('RUST_STATIC_LIB := %s\n' %
                            pretty_relpath(direct_linked, direct_linked.import_name))
 
+        for lib in direct_linked.linked_system_libs:
+            backend_file.write_once('OS_LIBS += %s\n' % lib)
+
     def _process_final_target_files(self, obj, files, backend_file):
         target = obj.install_target
         path = mozpath.basedir(target, (
             'dist/bin',
             'dist/xpi-stage',
             '_tests',
             'dist/include',
         ))
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -282,16 +282,17 @@ class CargoProvider(MachCommandBase):
     @CommandArgument('crates', default=None, nargs='*', help='The crate name(s) to check.')
     def check(self, all_crates=None, crates=None):
         # XXX duplication with `mach vendor rust`
         crates_and_roots = {
             'gkrust': 'toolkit/library/rust',
             'gkrust-gtest': 'toolkit/library/gtest/rust',
             'js': 'js/rust',
             'mozjs_sys': 'js/src',
+            'baldrdash': 'js/src/wasm/cranelift',
             'geckodriver': 'testing/geckodriver',
         }
 
         if all_crates:
             crates = crates_and_roots.keys()
         elif crates == None or crates == []:
             crates = ['gkrust']
 
--- a/toolkit/library/gtest/rust/Cargo.toml
+++ b/toolkit/library/gtest/rust/Cargo.toml
@@ -9,16 +9,17 @@ description = "Testing code for libgkrus
 bindgen = ["gkrust-shared/bindgen"]
 servo = ["gkrust-shared/servo"]
 quantum_render = ["gkrust-shared/quantum_render"]
 cubeb-remoting = ["gkrust-shared/cubeb-remoting"]
 cubeb_pulse_rust = ["gkrust-shared/cubeb_pulse_rust"]
 gecko_debug = ["gkrust-shared/gecko_debug"]
 simd-accel = ["gkrust-shared/simd-accel"]
 moz_memory = ["gkrust-shared/moz_memory"]
+spidermonkey_rust = ["gkrust-shared/spidermonkey_rust"]
 
 [dependencies]
 bench-collections-gtest = { path = "../../../../xpcom/rust/gtest/bench-collections" }
 mp4parse-gtest = { path = "../../../../dom/media/gtest" }
 nsstring-gtest = { path = "../../../../xpcom/rust/gtest/nsstring" }
 xpcom-gtest = { path = "../../../../xpcom/rust/gtest/xpcom" }
 gkrust-shared = { path = "../../rust/shared" }
 
--- a/toolkit/library/rust/Cargo.toml
+++ b/toolkit/library/rust/Cargo.toml
@@ -9,16 +9,17 @@ description = "Rust code for libxul"
 bindgen = ["gkrust-shared/bindgen"]
 servo = ["gkrust-shared/servo"]
 quantum_render = ["gkrust-shared/quantum_render"]
 cubeb-remoting = ["gkrust-shared/cubeb-remoting"]
 cubeb_pulse_rust = ["gkrust-shared/cubeb_pulse_rust"]
 gecko_debug = ["gkrust-shared/gecko_debug"]
 simd-accel = ["gkrust-shared/simd-accel"]
 moz_memory = ["gkrust-shared/moz_memory"]
+spidermonkey_rust = ["gkrust-shared/spidermonkey_rust"]
 
 [dependencies]
 gkrust-shared = { path = "shared" }
 
 [dev-dependencies]
 stylo_tests = { path = "../../../servo/ports/geckolib/tests/" }
 
 [lib]
--- a/toolkit/library/rust/gkrust-features.mozbuild
+++ b/toolkit/library/rust/gkrust-features.mozbuild
@@ -20,8 +20,11 @@ if CONFIG['MOZ_RUST_SIMD']:
 
 # This feature is only supported on Linux and macOS, and this check needs to
 # match MOZ_CUBEB_REMOTING in CubebUtils.cpp.
 if (CONFIG['OS_ARCH'] == 'Linux' and CONFIG['OS_TARGET'] != 'Android') or CONFIG['OS_ARCH'] == 'Darwin':
     gkrust_features += ['cubeb-remoting']
 
 if CONFIG['MOZ_MEMORY']:
     gkrust_features += ['moz_memory']
+
+if CONFIG['ENABLE_WASM_CRANELIFT']:
+    gkrust_features += ['spidermonkey_rust']
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -23,32 +23,34 @@ audioipc-client = { path = "../../../../
 audioipc-server = { path = "../../../../media/audioipc/server", optional = true }
 u2fhid = { path = "../../../../dom/webauthn/u2f-hid-rs" }
 rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }
 # We have these to enforce common feature sets for said crates.
 log = {version = "0.4", features = ["release_max_level_info"]}
 env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
 cose-c = { version = "0.1.5" }
 rkv = "0.4"
+jsrust_shared = { path = "../../../../js/src/rust/shared", optional = true }
 
 [build-dependencies]
 # Use exactly version 0.2.1, which uses semver 0.6, which other crates
 # require (0.2.2 requires 0.9)
 rustc_version = "=0.2.1"
 
 [features]
 default = []
 bindgen = ["geckoservo/bindgen"]
 servo = ["geckoservo"]
 quantum_render = ["webrender_bindings"]
 cubeb-remoting = ["cubeb-sys", "audioipc-client", "audioipc-server"]
 cubeb_pulse_rust = ["cubeb-sys", "cubeb-pulse"]
 gecko_debug = ["geckoservo/gecko_debug", "nsstring/gecko_debug"]
 simd-accel = ["encoding_c/simd-accel", "encoding_glue/simd-accel"]
 moz_memory = ["mp4parse_capi/mp4parse_fallible"]
+spidermonkey_rust = ["jsrust_shared"]
 
 [lib]
 path = "lib.rs"
 test = false
 doctest = false
 bench = false
 doc = false
 plugin = false
--- a/toolkit/library/rust/shared/lib.rs
+++ b/toolkit/library/rust/shared/lib.rs
@@ -26,16 +26,18 @@ extern crate encoding_glue;
 extern crate audioipc_client;
 #[cfg(feature = "cubeb-remoting")]
 extern crate audioipc_server;
 extern crate env_logger;
 extern crate u2fhid;
 extern crate log;
 extern crate cosec;
 extern crate rsdparsa_capi;
+#[cfg(feature = "spidermonkey_rust")]
+extern crate jsrust_shared;
 
 use std::boxed::Box;
 use std::env;
 use std::ffi::{CStr, CString};
 use std::os::raw::c_char;
 #[cfg(target_os = "android")]
 use std::os::raw::c_int;
 #[cfg(target_os = "android")]