Files
Hiroshi SHIBATAandClaude Opus 5.5 c85cb72bcc [DOC] Move debugging out of building_ruby.md
The section has grown past building with the crash dumps, so give it its own page next to building and testing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:47:05 +09:00

287 lines
8.5 KiB
Markdown

# Building Ruby
## 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
* [gperf] - 3.1 or later
* Usually unneeded; only if you edit some source files using gperf
* ruby - 3.1 or later
* We can upgrade this version to system ruby version of the latest
Ubuntu LTS.
* git - 2.32 or later
* Earlier versions may work; 2.32 or later will prevent build
errors in case your system `.gitconfig` uses `$HOME` paths.
2. Install optional, recommended dependencies:
* [libffi] (to build fiddle)
* [gmp] (if you wish to accelerate Bignum operations)
* [rustc] - 1.58.0 or later, if you wish to build
[YJIT](rdoc-ref:RubyVM::YJIT).
If you want to link the libraries (e.g., gmp) installed into other than
the OS default place, typically using Homebrew on macOS, pass the
`--with-opt-dir` (or `--with-gmp-dir` for gmp) option to `configure`.
```sh
configure --with-opt-dir=$(brew --prefix gmp):$(brew --prefix jemalloc)
```
As for the libraries needed for particular extensions only and not for
Ruby (openssl, readline, libyaml, zlib), you can add `--with-EXTLIB-dir`
options to the command line or to `CONFIGURE_ARGS` environment variable.
The command line options will be embedded in `rbconfig.rb`, while the
latter environment variable is not embedded and is only used when
building the extension libraries.
```sh
export CONFIGURE_ARGS=""
for ext in openssl readline libyaml zlib; do
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-$ext-dir=$(brew --prefix $ext)"
done
```
[OpenSSL]: https://www.openssl.org
[LibreSSL]: https://www.libressl.org
[libyaml]: https://github.com/yaml/libyaml/
[zlib]: https://www.zlib.net
[autoconf]: https://www.gnu.org/software/autoconf/
[gperf]: https://www.gnu.org/software/gperf/
[libffi]: https://sourceware.org/libffi/
[gmp]: https://gmplib.org
[rustc]: https://www.rust-lang.org
## Quick start guide
1. Download ruby source code:
Select one of the below.
1. Build from the tarball:
Download the latest tarball from [Download Ruby] page and extract
it. Example for Ruby 3.0.2:
```sh
tar -xzf ruby-3.0.2.tar.gz
cd ruby-3.0.2
```
2. Build from the git repository:
Checkout the CRuby source code:
```sh
git clone https://github.com/ruby/ruby.git
cd ruby
```
Run the GNU Autoconf script (which generates the `configure` script):
```sh
./autogen.sh
```
2. Create a `build` directory inside the repository directory:
```sh
mkdir build && cd build
```
While it's not necessary to build in a dedicated directory like this, it's good
practice to do so.
3. We'll eventually install our new Ruby in `~/.rubies/ruby-master`, so we'll create that directory:
```sh
mkdir ~/.rubies
```
4. Run the `configure` script (which generates the `Makefile`):
```sh
../configure --prefix="${HOME}/.rubies/ruby-master"
```
- Also `-C` (or `--config-cache`) would reduce time to configure from the
next time.
5. Build Ruby:
```sh
make
```
6. [Run tests](testing_ruby.md) to confirm your build succeeded.
7. Install our newly-compiled Ruby into `~/.rubies/ruby-master`:
```sh
make install
```
- 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`.
8. You can then try your new Ruby out, for example:
```sh
~/.rubies/ruby-master/bin/ruby -e "puts 'Hello, World!'"
```
By the end, your repo will look like this:
```text
ruby
├── autogen.sh # Pre-existing Autoconf script, used in step 1
├── configure # Generated in step 1, which generates the `Makefile` in step 4
├── build # Created in step 2 and populated in step 4
│ ├── GNUmakefile # Generated by `../configure`
│ ├── Makefile # Generated by `../configure`
│ ├── object.o # Compiled object file, built by `make`
│ └── ... other compiled `.o` object files
│
│ # Other interesting files:
├── include
│ └── ruby.h # The main public header
├── internal
│ ├── object.h
│ └── ... other header files used by the `.c` files in the repo root.
├── lib
│ └── # Default gems, like `bundler`, `erb`, `set`, `yaml`, etc.
├── spec
│ └── # A mirror of the Ruby specification from github.com/ruby/spec
├── test
│ ├── ruby
│ └── ...
├── object.c
└── ... other `.c` files
```
[Download Ruby]: https://www.ruby-lang.org/en/downloads/
### 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 in [the separated
file](../distribution/windows.md).
## More details
If you're interested in continuing development on Ruby, here are more details
about Ruby's build to help out.
### Running make scripts in parallel
In GNU make[^caution-gmake-3] 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:
```sh
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:
```sh
# 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)"
```
[^caution-gmake-3]: **CAUTION**: GNU make 3 is missing some features for parallel execution, we
recommend to upgrade to GNU make 4 or later.
### 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:
```sh
make miniruby
```
### Statically linking extensions
`configure --with-static-linked-ext` links the extension libraries under `ext/`
into the `ruby` binary instead of building them as separate `.so`/`.bundle`
files, and makes `RbConfig::CONFIG["EXTSTATIC"]` `"static"`. Bundled gems that
have C extensions, such as `bigdecimal` and `fiddle`, are unaffected and are
still built as loadable objects.
The external libraries the extensions need are then linked into `ruby` itself,
so pass `--with-EXTLIB-dir` to `configure` rather than putting the paths in
`LDFLAGS` by hand. On macOS with Homebrew:
```sh
./configure --with-static-linked-ext --with-openssl-dir=$(brew --prefix openssl@3)
```
`brew --prefix LIB` prints a path even for a formula that is not installed, so
generating `LDFLAGS` from it can yield `-L` options for directories that do not
exist, which `configure` rejects. Use `brew --prefix --installed LIB`, which
fails instead of printing a path for an uninstalled formula.
## Debugging
See [Debugging Ruby](debugging_ruby.md).
## How to measure coverage of C and Ruby code
You need to be able to use gcc (gcov) and lcov visualizer.
```sh
./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