summaryrefslogtreecommitdiff
path: root/doc/contributing/building_ruby.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/contributing/building_ruby.md')
-rw-r--r--doc/contributing/building_ruby.md191
1 files changed, 172 insertions, 19 deletions
diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md
index f20eacc0ae..96cee40cb4 100644
--- a/doc/contributing/building_ruby.md
+++ b/doc/contributing/building_ruby.md
@@ -1,41 +1,120 @@
# Building Ruby
-## Quick start guide
+## Dependencies
1. Install the prerequisite dependencies for building the CRuby interpreter:
* C compiler
+
+ For RubyGems, you will also need:
+
+ * OpenSSL 1.1.x or 3.0.x / LibreSSL
+ * libyaml 0.1.7 or later
+ * zlib
+
+ If you want to build from the git repository, you will also need:
+
* autoconf - 2.67 or later
- * bison - 2.0 or later
- * gperf - 3.0.3 or later
- * ruby - 2.7 or later
+ * gperf - 3.1 or later
+ * Usually unneeded; only if you edit some source files using gperf
+ * ruby - 3.0 or later
+ * We can upgrade this version to system ruby version of the latest Ubuntu LTS.
2. Install optional, recommended dependencies:
- * OpenSSL/LibreSSL
- * readline/editline (libedit)
- * zlib
- * libffi
- * libyaml
+ * libffi (to build fiddle)
+ * gmp (if you with to accelerate Bignum operations)
* libexecinfo (FreeBSD)
+ * rustc - 1.58.0 or later, if you wish to build
+ [YJIT](https://docs.ruby-lang.org/en/master/RubyVM/YJIT.html).
-3. Checkout the CRuby source code:
+ If you installed the libraries needed for extensions (openssl, readline, libyaml, zlib) into other than the OS default place,
+ typically using Homebrew on macOS, add `--with-EXTLIB-dir` options to `CONFIGURE_ARGS` environment variable.
+ ``` shell
+ export CONFIGURE_ARGS=""
+ for ext in openssl readline libyaml zlib; do
+ CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-$ext-dir=$(brew --prefix $ext)"
+ done
```
- git clone https://github.com/ruby/ruby.git
+
+## Quick start guide
+
+1. Download ruby source code:
+
+ Select one of the below.
+
+ 1. Build from the tarball:
+
+ Download the latest tarball from [ruby-lang.org](https://www.ruby-lang.org/en/downloads/) and
+ extract it. Example for Ruby 3.0.2:
+
+ ``` shell
+ tar -xzf ruby-3.0.2.tar.gz
+ cd ruby-3.0.2
+ ```
+
+ 2. Build from the git repository:
+
+ Checkout the CRuby source code:
+
+ ``` shell
+ git clone https://github.com/ruby/ruby.git
+ cd ruby
+ ```
+
+ Generate the configure file:
+
+ ``` shell
+ ./autogen.sh
+ ```
+
+2. Create a `build` directory separate from the source directory:
+
+ ``` shell
+ mkdir build && cd build
```
-4. Generate the configuration files and build:
+ While it's not necessary to build in a separate directory, it's good practice to do so.
+
+3. We'll install Ruby in `~/.rubies/ruby-master`, so create the directory:
+ ``` shell
+ mkdir ~/.rubies
```
- ./autogen.sh
- mkdir build && cd build # its good practice to build outside of source dir
- mkdir ~/.rubies # we will install to .rubies/ruby-master in our home dir
+
+4. Run configure:
+
+ ``` shell
../configure --prefix="${HOME}/.rubies/ruby-master"
+ ```
+
+ - Also `-C` (or `--config-cache`) would reduce time to configure from the next time.
+
+5. Build Ruby:
+
+ ``` shell
+ make
+ ```
+
+6. [Run tests](testing_ruby.md) to confirm your build succeeded.
+
+7. Install Ruby:
+
+ ``` shell
make install
```
-5. [Run tests](testing_ruby.md) to confirm your build succeeded
+ - If you need to run `make install` with `sudo` and want to avoid document generation with different permissions, you can use
+ `make SUDO=sudo install`.
+
+### Unexplainable Build Errors
+
+If you are having unexplainable build errors, after saving all your work, try running `git clean -xfd` in the source root to remove all git ignored local files. If you are working from a source directory that's been updated several times, you may have temporary build artifacts from previous releases which can cause build failures.
+
+## Building on Windows
+
+The documentation for building on Windows can be found [here](../windows.md).
## More details
@@ -44,20 +123,38 @@ about Ruby's build to help out.
### Running make scripts in parallel
-To run make scripts in parallel, pass flag `-j<number of processes>`. For instance,
+In GNU make and BSD make implementations, to run a specific make script in parallel, pass the flag `-j<number of processes>`. For instance,
to run tests on 8 processes, use:
-```
+``` shell
make test-all -j8
```
+We can also set `MAKEFLAGS` to run _all_ `make` commands in parallel.
+
+Having the right `--jobs` flag will ensure all processors are utilized when building software projects. To do this effectively, you can set `MAKEFLAGS` in your shell configuration/profile:
+
+``` shell
+# On macOS with Fish shell:
+export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu)
+
+# On macOS with Bash/ZSH shell:
+export MAKEFLAGS="--jobs $(sysctl -n hw.ncpu)"
+
+# On Linux with Fish shell:
+export MAKEFLAGS="--jobs "(nproc)
+
+# On Linux with Bash/ZSH shell:
+export MAKEFLAGS="--jobs $(nproc)"
+```
+
### Miniruby vs Ruby
Miniruby is a version of Ruby which has no external dependencies and lacks certain features.
It can be useful in Ruby development because it allows for faster build times. Miniruby is
built before Ruby. A functional Miniruby is required to build Ruby. To build Miniruby:
-```
+``` shell
make miniruby
```
@@ -72,3 +169,59 @@ with the Ruby script you'd like to run. You can use the following make targets:
* `make runruby`: Runs `test.rb` using Ruby
* `make lldb-ruby`: Runs `test.rb` using Ruby in lldb
* `make gdb-ruby`: Runs `test.rb` using Ruby in gdb
+
+### Compiling for Debugging
+
+You should configure Ruby without optimization and other flags that may interfere with debugging:
+
+``` shell
+./configure --enable-debug-env optflags="-O0 -fno-omit-frame-pointer"
+```
+
+### Building with Address Sanitizer
+
+Using the address sanitizer (ASAN) is a great way to detect memory issues. It can detect memory safety issues in Ruby itself, and also in any C extensions compiled with and loaded into a Ruby compiled with ASAN.
+
+``` shell
+./autogen.sh
+mkdir build && cd build
+../configure CC=clang cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like
+make
+```
+The compiled Ruby will now automatically crash with a report and a backtrace if ASAN detects a memory safety issue. To run Ruby's test suite under ASAN, issue the following command. Note that this will take quite a long time (over two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and `SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't spuriously fail with timeouts when in fact they're just slow.
+
+``` shell
+RUBY_TEST_TIMEOUT_SCALE=5 SYNTAX_SUGGEST_TIMEOUT=600 make check
+```
+
+Please note, however, the following caveats!
+
+* ASAN will not work properly on any currently released version of Ruby; the necessary support is currently only present on Ruby's master branch (and the whole test suite passes only as of commit [9d0a5148ae062a0481a4a18fbeb9cfd01dc10428](https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428))
+* Due to [this bug](https://bugs.ruby-lang.org/issues/20243), Clang generates code for threadlocal variables which doesn't work with M:N threading. Thus, it's necessary to disable M:N threading support at build time for now (with the `-DUSE_MN_THREADS=0` configure argument).
+* Currently, ASAN will only work correctly when using a recent head build of LLVM/Clang - it requires [this bugfix](https://github.com/llvm/llvm-project/pull/75290) related to multithreaded `fork`, which is not yet in any released version. See [here](https://llvm.org/docs/CMake.html) for instructions on how to build LLVM/Clang from source (note you will need at least the `clang` and `compiler-rt` projects enabled). Then, you will need to replace `CC=clang` in the instructions with an explicit path to your built Clang binary.
+* ASAN has only been tested so far with Clang on Linux. It may or may not work with other compilers or on other platforms - please file an issue on [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if you run into problems with such configurations (or, to report that they actually work properly!)
+* In particular, although I have not yet tried it, I have reason to believe ASAN will _not_ work properly on macOS yet - the fix for the multithreaded fork issue was actually reverted for macOS (see [here](https://github.com/llvm/llvm-project/commit/2a03854e4ce9bb1bcd79a211063bc63c4657f92c)). Please open an issue on [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if this is a problem for you.
+
+## How to measure coverage of C and Ruby code
+
+You need to be able to use gcc (gcov) and lcov visualizer.
+
+``` shell
+./autogen.sh
+./configure --enable-gcov
+make
+make update-coverage
+rm -f test-coverage.dat
+make test-all COVERAGE=true
+make lcov
+open lcov-out/index.html
+```
+
+If you need only C code coverage, you can remove `COVERAGE=true` from the above process.
+You can also use `gcov` command directly to get per-file coverage.
+
+If you need only Ruby code coverage, you can remove `--enable-gcov`.
+Note that `test-coverage.dat` accumulates all runs of `make test-all`.
+Make sure that you remove the file if you want to measure one test run.
+
+You can see the coverage result of CI: https://rubyci.org/coverage