Build System

There are many ways to build prism, which means the build system is a bit more complicated than usual.

Requirements

The main solution for the second point seems a Makefile, otherwise many of the usages would have to duplicate the logic to build prism.

General Design

  1. Templates are generated by templates/template.rb

  2. The Makefile compiles both libprism.a and libprism.{so,dylib,dll} from the src/*/.c and include/*/.h files

  3. The Rakefile :compile task ensures the above prerequisites are done, then calls make, and uses Rake::ExtensionTask to compile the C extension (using its extconf.rb), which uses libprism.a

This way there is minimal duplication, and each layer builds on the previous one and has its own responsibilities.

The static library exports no symbols, to avoid any conflict. The shared library exports some symbols, and this is fine since there should only be one libprism shared library loaded per process (i.e., at most one version of the prism gem loaded in a process, only the gem uses the shared library).

The various ways to build prism

Building from ruby/prism repository with bundle exec rake

rake calls make and then uses Rake::ExtensionTask to compile the C extension (see above).

Building the prism gem by gem install/bundle install

The gem contains the pre-generated templates. When installing the gem, extconf.rb is used and that: * runs make build/libprism.a * compiles the C extension with mkmf

When installing the gem on JRuby and TruffleRuby, no C extension is built, so instead of the last step, there is Ruby code using FFI which uses libprism.{so,dylib,dll} to implement the same methods as the C extension, but using serialization instead of many native calls/accesses (JRuby does not support C extensions, serialization is faster on TruffleRuby than the C extension).

Building the prism gem from git, e.g. gem "prism", github: "ruby/prism"

The same as above, except the extconf.rb additionally runs first: * templates/template.rb to generate the templates

Because of course those files are not part of the git repository.

Building prism as part of CRuby

This script imports prism sources in CRuby.

The script generates the templates when importing.

prism’s Makefile is not used at all in CRuby. Instead, CRuby’s Makefile is used.

Building prism as part of TruffleRuby

This script imports prism sources in TruffleRuby. The script generates the templates when importing.

Then when mx build builds TruffleRuby and the prism mx project inside, it runs make.

Then the prism bindings mx project is built, which contains the bindings and links to libprism.a (to avoid exporting symbols, so no conflict when installing the prism gem).

Building prism as part of JRuby

TODO, similar to TruffleRuby.

Building prism for embedded system

For instance, you can build a static library libprism.a targeting the Arm Cortex-M0+ embedded system by the commands below:

The build process internally looks up _POSIX_MAPPED_FILES and _WIN32 macros to determine whether the functions of the memory map are available on the target platform.

Building prism with custom memory allocator

If you need to use memory allocation functions implemented outside of the standard library, follow these steps:

For further clarity, refer to include/prism/defines.h.

Building prism from source as a C library

All of the source files match src/*/.c and all of the headers match include/*/.h.

If you want to build prism as a shared library and link against it, you should compile with:

Flags

make respects the MAKEFLAGS environment variable. As such, to speed up the build you can run:

MAKEFLAGS="-j10" bundle exec rake compile

Build options