Skip to content

Commit 638ff2b

Browse files
committed
JITs: Drop cargo and use just rustc for release combo build
So we don't expose builders to network flakiness which cannot be worked around using cargo's --offline flag.
1 parent 86102ad commit 638ff2b

9 files changed

Lines changed: 110 additions & 48 deletions

File tree

Cargo.toml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
# Using Cargo's workspace feature to build all the Rust code in
2-
# into a single package.
3-
# TODO(alan) notes about rust version requirements. Undecided yet.
1+
# This is the root Cargo [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html)
2+
# and the root package for all the rust code that are statically linked into ruby. Rust tooling
3+
# limitations means all Rust code need to share a single archive library (staticlib) at the
4+
# integration point with non-rust code. (See rustlang/rust#44322 and #104707 for a taste of
5+
# the linking challenges.)
6+
#
7+
# Do not add required dependencies. This is a policy that helps downstream consumers and give
8+
# us tight control over what we ship. All of the optional dependencies are used exclusively
9+
# during development.
10+
#
11+
# Release builds avoid Cargo entirely because offline builds can fail even when none of the
12+
# optional dependencies are built (rust-lang/cargo#10352).
413

514
[workspace]
615
members = ["zjit", "yjit", "jit"]

common.mk

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,8 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
268268

269269
# For release builds
270270
YJIT_RUSTC_ARGS = --crate-name=yjit \
271-
--crate-type=staticlib \
271+
$(JIT_RUST_FLAGS) \
272272
--edition=2021 \
273-
--cfg 'feature="stats_allocator"' \
274273
-g \
275274
-C lto=thin \
276275
-C opt-level=3 \
@@ -279,9 +278,8 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \
279278
'$(top_srcdir)/yjit/src/lib.rs'
280279

281280
ZJIT_RUSTC_ARGS = --crate-name=zjit \
282-
--crate-type=staticlib \
281+
$(JIT_RUST_FLAGS) \
283282
--edition=2024 \
284-
--cfg 'feature="stats_allocator"' \
285283
-g \
286284
-C lto=thin \
287285
-C opt-level=3 \

configure.ac

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3896,7 +3896,6 @@ AC_SUBST(INSTALL_STATIC_LIBRARY)
38963896

38973897
[begin]_group "JIT section" && {
38983898
AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix
3899-
AC_CHECK_TOOL(CARGO, [cargo], [no])
39003899

39013900
dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0)
39023901
JIT_RUSTC_OK=no
@@ -3963,11 +3962,7 @@ AC_ARG_ENABLE(zjit,
39633962
# 1.85.0 is the first stable version that supports the 2024 edition.
39643963
AS_IF([test "$RUSTC" != "no" && echo "#[cfg(target_arch = \"$JIT_TARGET_ARCH\")] fn main() {}" |
39653964
$RUSTC - --edition=2024 --emit asm=/dev/null 2>/dev/null],
3966-
AS_IF([test "$gnumake" = "yes" -a \( "$YJIT_SUPPORT" = "no" -o "$CARGO" != "no" \)], [
3967-
# When only building ZJIT, we don't need cargo; it's required for YJIT+ZJIT build.
3968-
# Assume that if rustc is new enough, then cargo is also.
3969-
# TODO(alan): Get rid of dependency on cargo in YJIT+ZJIT build. Cargo's offline mode
3970-
# still too unreliable: https://github.com/rust-lang/cargo/issues/10352
3965+
AS_IF([test "$gnumake" = "yes"], [
39713966
rb_zjit_build_possible=yes
39723967
])
39733968
)
@@ -4053,36 +4048,49 @@ AS_CASE(["${ZJIT_SUPPORT}"],
40534048
AC_DEFINE(USE_ZJIT, 0)
40544049
])
40554050

4056-
# if YJIT+ZJIT release build, or any build that requires Cargo
4057-
AS_IF([test x"$JIT_CARGO_SUPPORT" != "xno" -o \( x"$YJIT_SUPPORT" != "xno" -a x"$ZJIT_SUPPORT" != "xno" \)], [
4058-
AS_IF([test x"$CARGO" = "xno"],
4059-
AC_MSG_ERROR([this build configuration requires cargo. Installation instructions available at https://www.rust-lang.org/tools/install]))
4060-
4061-
YJIT_LIBS=
4062-
ZJIT_LIBS=
4063-
4064-
# There's more processing below to get the feature set for the
4065-
# top-level crate, so capture at this point for feature set of
4066-
# just the zjit crate.
4067-
ZJIT_TEST_FEATURES="${rb_cargo_features}"
4051+
JIT_RUST_FLAGS='--crate-type=staticlib --cfg feature=\"stats_allocator\"'
4052+
RLIB_DIR=
4053+
AS_CASE(["$JIT_CARGO_SUPPORT:$YJIT_SUPPORT:$ZJIT_SUPPORT"],
4054+
[no:yes:yes], [ # release build of YJIT+ZJIT
4055+
YJIT_LIBS=
4056+
ZJIT_LIBS=
4057+
JIT_RUST_FLAGS="--crate-type=rlib"
4058+
RLIB_DIR="target/release"
4059+
RUST_LIB="target/release/libruby.a"
4060+
],
4061+
[no:*], [],
4062+
[*], [ # JIT_CARGO_SUPPORT not "no" -- cargo required.
4063+
AC_CHECK_TOOL(CARGO, [cargo], [no])
4064+
AS_IF([test x"$CARGO" = "xno"],
4065+
AC_MSG_ERROR([this build configuration requires cargo. Installation instructions available at https://www.rust-lang.org/tools/install]))
4066+
4067+
YJIT_LIBS=
4068+
ZJIT_LIBS=
4069+
4070+
# There's more processing below to get the feature set for the
4071+
# top-level crate, so capture at this point for feature set of
4072+
# just the zjit crate.
4073+
ZJIT_TEST_FEATURES="${rb_cargo_features}"
4074+
4075+
AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [
4076+
rb_cargo_features="$rb_cargo_features,yjit"
4077+
])
4078+
AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [
4079+
AC_SUBST(ZJIT_TEST_FEATURES)
4080+
rb_cargo_features="$rb_cargo_features,zjit"
4081+
])
4082+
# if YJIT and ZJIT release mode
4083+
AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [
4084+
JIT_CARGO_SUPPORT=release
4085+
])
4086+
CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}"
4087+
AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [
4088+
RUST_LIB="target/debug/libruby.a"
4089+
], [
4090+
RUST_LIB="target/${JIT_CARGO_SUPPORT}/libruby.a"
4091+
])
4092+
],
40684093

4069-
AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [
4070-
rb_cargo_features="$rb_cargo_features,yjit"
4071-
])
4072-
AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [
4073-
AC_SUBST(ZJIT_TEST_FEATURES)
4074-
rb_cargo_features="$rb_cargo_features,zjit"
4075-
])
4076-
# if YJIT and ZJIT release mode
4077-
AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [
4078-
JIT_CARGO_SUPPORT=release
4079-
])
4080-
CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}"
4081-
AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [
4082-
RUST_LIB="target/debug/libruby.a"
4083-
], [
4084-
RUST_LIB="target/${JIT_CARGO_SUPPORT}/libruby.a"
4085-
])
40864094
])
40874095

40884096
# In case either we're linking rust code
@@ -4098,6 +4106,7 @@ AS_IF([test -n "$RUST_LIB"], [
40984106

40994107
dnl These variables end up in ::RbConfig::CONFIG
41004108
AC_SUBST(RUSTC)dnl Rust compiler command
4109+
AC_SUBST(JIT_RUST_FLAGS)dnl the common rustc flags for JIT crates such as zjit
41014110
AC_SUBST(CARGO)dnl Cargo command for Rust builds
41024111
AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
41034112
AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
@@ -4108,6 +4117,7 @@ AC_SUBST(ZJIT_LIBS)dnl path to the .a library of ZJIT
41084117
AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of ZJIT
41094118
AC_SUBST(JIT_OBJ)dnl for optionally building C glue code for Rust FFI
41104119
AC_SUBST(RUST_LIB)dnl path to the rust .a library that contains either or both JITs
4120+
AC_SUBST(RLIB_DIR)dnl subpath of build directory for .rlib files
41114121
AC_SUBST(JIT_CARGO_SUPPORT)dnl "no" or the cargo profile of the rust code
41124122
}
41134123

defs/jit.mk

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ $(RUST_LIB): $(srcdir)/ruby.rs
3030
MACOSX_DEPLOYMENT_TARGET=11.0 \
3131
$(CARGO) $(CARGO_VERBOSE) build --manifest-path '$(top_srcdir)/Cargo.toml' $(CARGO_BUILD_ARGS)
3232
$(RUST_LIB_TOUCH)
33+
else ifneq ($(strip $(RLIB_DIR)),) # combo build
34+
35+
$(RUST_LIB): $(srcdir)/ruby.rs
36+
$(ECHO) 'building $(@F)'
37+
$(Q) $(RUSTC) --edition=2024 \
38+
'-L$(@D)' \
39+
--extern=yjit \
40+
--extern=zjit \
41+
--crate-type=staticlib \
42+
--cfg 'feature="yjit"' \
43+
--cfg 'feature="zjit"' \
44+
'--out-dir=$(@D)' \
45+
'$(top_srcdir)/ruby.rs'
46+
47+
# Absolute path to avoid VPATH ambiguity
48+
JIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libjit.rlib
49+
$(YJIT_RLIB): $(JIT_RLIB)
50+
$(ZJIT_RLIB): $(JIT_RLIB)
51+
$(JIT_RLIB):
52+
$(ECHO) 'building $(@F)'
53+
$(Q) $(RUSTC) --crate-name=jit \
54+
--edition=2024 \
55+
$(JIT_RUST_FLAGS) \
56+
'--out-dir=$(@D)' \
57+
'$(top_srcdir)/jit/src/lib.rs'
3358
endif # ifneq ($(JIT_CARGO_SUPPORT),no)
3459

3560
RUST_LIB_SYMBOLS = $(RUST_LIB:.a=).symbols

template/Makefile.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ JIT_CARGO_SUPPORT=@JIT_CARGO_SUPPORT@
114114
CARGO_TARGET_DIR=@abs_top_builddir@/target
115115
CARGO_BUILD_ARGS=@CARGO_BUILD_ARGS@
116116
ZJIT_TEST_FEATURES=@ZJIT_TEST_FEATURES@
117+
JIT_RUST_FLAGS=@JIT_RUST_FLAGS@
118+
RLIB_DIR=@RLIB_DIR@
117119
RUST_LIB=@RUST_LIB@
118120
RUST_LIBOBJ = $(RUST_LIB:.a=.@OBJEXT@)
119121
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@

yjit/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ rust-version = "1.58.0" # Minimally supported rust version
1010
publish = false # Don't publish to crates.io
1111

1212
[dependencies]
13-
# No required dependencies to simplify build process. TODO: Link to yet to be
14-
# written rationale. Optional For development and testing purposes
13+
# No required dependencies to simplify build process.
14+
# Optional For development and testing purposes.
1515
capstone = { version = "0.13.0", optional = true }
1616
jit = { version = "0.1.0", path = "../jit" }
1717

yjit/yjit.mk

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ yjit-libs: $(BUILD_YJIT_LIBS)
1919
$(BUILD_YJIT_LIBS): $(YJIT_SRC_FILES)
2020
$(ECHO) 'building Rust YJIT (release mode)'
2121
$(Q) $(RUSTC) $(YJIT_RUSTC_ARGS)
22-
endif
22+
else ifneq ($(strip $(RLIB_DIR)),) # combo build
23+
# Absolute path to avoid VPATH ambiguity
24+
YJIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libyjit.rlib
25+
26+
$(YJIT_RLIB): $(YJIT_SRC_FILES)
27+
$(ECHO) 'building $(@F)'
28+
$(Q) $(RUSTC) '-L$(@D)' --extern=jit $(YJIT_RUSTC_ARGS)
29+
30+
$(RUST_LIB): $(YJIT_RLIB)
31+
endif # ifneq ($(strip $(YJIT_LIBS)),)
2332

2433
ifneq ($(YJIT_SUPPORT),no)
2534
$(RUST_LIB): $(YJIT_SRC_FILES)

zjit/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ rust-version = "1.85.0" # Minimally supported rust version
66
publish = false # Don't publish to crates.io
77

88
[dependencies]
9-
# No required dependencies to simplify build process. TODO: Link to yet to be
10-
# written rationale. Optional For development and testing purposes
9+
# No required dependencies to simplify build process.
10+
# Optional For development and testing purposes.
1111
capstone = { version = "0.13.0", optional = true }
1212
jit = { version = "0.1.0", path = "../jit" }
1313

zjit/zjit.mk

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,16 @@ ifneq ($(strip $(ZJIT_LIBS)),)
2323
$(BUILD_ZJIT_LIBS): $(ZJIT_SRC_FILES)
2424
$(ECHO) 'building Rust ZJIT (release mode)'
2525
$(Q) $(RUSTC) $(ZJIT_RUSTC_ARGS)
26-
endif
26+
else ifneq ($(strip $(RLIB_DIR)),) # combo build
27+
# Absolute path to avoid VPATH ambiguity
28+
ZJIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libzjit.rlib
29+
30+
$(ZJIT_RLIB): $(ZJIT_SRC_FILES)
31+
$(ECHO) 'building $(@F)'
32+
$(Q) $(RUSTC) '-L$(@D)' --extern=jit $(ZJIT_RUSTC_ARGS)
33+
34+
$(RUST_LIB): $(ZJIT_RLIB)
35+
endif # ifneq ($(strip $(ZJIT_LIBS)),)
2736

2837
# By using ZJIT_BENCH_OPTS instead of RUN_OPTS, you can skip passing the options to `make install`
2938
ZJIT_BENCH_OPTS = $(RUN_OPTS) --enable-gems

0 commit comments

Comments
 (0)