📐Reason/OCaml rules and tools for Bazel
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.travis
examples
patched_modules
reason
retool
tools
.bazelrc
.gitignore
.travis.yml
BUILD
LICENSE
README.rst
SPEC.md
WORKSPACE

README.rst

ReasonML / BuckleScript Rules

https://travis-ci.org/ostera/rules_reason.svg?branch=master

A collection of OCaml, ReasonML, and BuckleScript rules and tools for Bazel.

Note: this is alpha software! I'm building it to properly integrate a ReasonML application into a bigger project that builds with Bazel.

This projet relies on two prerequisites:

  1. nix, the purely functional package manager, which is used for installing the ReasonML tooling (refmt specifically), opam, yarn and node in an hermetic-ish fashion. At least you don't need to handle those yourself :)
  2. bazel, naturally.

If you just cloned this repo and you have both those tools installed, feel free to start with a bazel build //... to get everything warmed up.

The examples works a separate workspace so you will need to run bazel build //... there as well if you wish to play around with them.

WARNING: because this rules handle all of their dependencies hermetically, a clean install takes a good ~10 minutes on an early 2015 Macbook Pro.

Getting Started

Begin by adding the following to your WORKSPACE:

workspace(name = "retool")

###
### Reason Rules!
###

rules_reason_version = "f8b956b147bfcf22c90480e7ebea32e6769c1fe0" # HEAD

http_archive(
    name = "com_github_ostera_rules_reason",
    sha256 = "",
    strip_prefix = "rules_reason-%s" % (rules_reason_version,),
    urls = ["https://github.com/ostera/rules_reason/archive/%s.zip" % (rules_reason_version,)],
    )

###
### Nix Repositories
###

load(
    "@com_github_ostera_rules_reason//reason/repositories:nix.bzl",
    "nix_repositories",
)

nix_repositories(
    nix_sha256 = "28121f6eb3d6c5b4c1fc9f716953ce8b0a793b841d0e9de095977b3ade06f92d",
    nix_version = "20a78f74f8ac70d1099ff0d214cd00b25820da03",
)

###
### Register Reason Toolchain
###

load(
    "@com_github_ostera_rules_reason//reason:def.bzl",
    "reason_register_toolchains",
)

reason_register_toolchains(
    bs_sha256 = "db3f37eb27bc1653c3045e97adaa83e800dff55ce093d78ddfe85e85165e2125",
    bs_version = "939ef1e1e874c80ff9df74b16dab1dbe2e2df289",
    nixpkgs_revision = "d91a8a6ece07f5a6df82aa5dc02030d9c6724c27",
    nixpkgs_sha256 = "0c5291bcf7d909cc4b18a24effef03f717d6374de377f91324725c646d494857",
)

################################################################################
#
#   Declare dependencies
#
################################################################################

load(
    "//3rdparty:load.bzl",
    "declare_dependencies"
)

declare_dependencies()

Use reason_module to compile a group of .re and .rei files into their corresponding .ml and .mli counterparts.

Further consume these outputs with ocaml_module, bs_module, ocaml_bytecode_binary, or ocaml_native_binary.

Compiling to Javascript

You can use bs_module to turn any ML source target into Javascript, this includes the outputs from a reason_module rule too.

Unfortunately bsc requires a bsconfig.json file at the place where you call it. This means that you need to have that file at the root of your project.

# BUILD file at //...
filegroup(
  name = "bsconfig",
  srcs = ["bsconfig.json"],
)

# BUILD file somewhere in your sources!
reason_module(
  name = "srcs.re",
  srcs = glob(["*.re"]),
)

bs_module(
  name = "srcs.js",
  config = ["//:bsconfig"],
  srcs = [":srcs.re"],
  deps = [":deps"],
)

Compiling to Native and Bytecode

You can use ocaml_native_binary and ocaml_bytecode_binary to compile your ML sources into native or bytecode binaries, and yes you can use your reason_module targets as sources!

# BUILD file somewhere in your sources!
reason_module(
    name = "srcs",
    srcs = glob(["*.re"]),
    )

ocaml_native_binary(
    name = "native",
    srcs = [":srcs"],
  )

ocaml_bytecode_binary(
    name = "bytecode",
    srcs = [":srcs"],
  )

What's next?

In no particular order:

  1. DevFlow: Top-Level
  2. DevFlow: Dependencies
  3. DevFlow: Generating Merlin and pointing IDEs to the right places
  4. Rules: *_test
  5. DevFlow: Auto-rebuild
  6. Rules: node_binary
  7. < your suggestion here! >

Rules

reason_module

This compiles down ReasonML code into a representation that is friendly for BuckleScript or the default Ocaml compiler.

Which one will it be compatible with is determined by how you write your ReasonML code.

Name Type Default value
name string mandatory value
A unique name for this rule.
srcs string_list mandatory value

The sources of this library.

The name of the sources will be preserved, and the outputs will replace the .re or .rei extension with .ml or .mli correspondingly.

Other bs_module rules can depend on this library to compile it down to Javascript code.

toolchain label
value:"//reason/toolchain:bs-platform"

The toolchain to use when building this rule.

It should include both refmt, bsc and a filegroup containing the BuckleScript stdlib.

Example:

# //my_app/BUILD
load(
    "@com_github_ostera_rules_reason//reason:def.bzl",
    "reason_module",
)

reason_module(
    name = "my_app",
    srcs = glob(["*.re", "*.rei"])
    visibility = ["//my_app:__subpackages__"],
  )

bs_module

Compile Ocaml code into Javascript.

Name Type Default value
name string mandatory value
A unique name for this rule.
config label mandatory value

The bsconfig.json file.

The file must be located at the root of your WORKSPACE. Currently looking to work around this.

srcs string_list mandatory value

The ML sources of this library.

The name of the sources will be preserved, and the outputs will replace the .ml by their compilation counterparts (.cmi, .cmj, .cmt, etc) and the .js output.

Other bs_module rules can depend on this library to compile it down to Javascript code.

deps label_list
value:[]
Dependencies of this library, must include BsModuleInfo providers.
toolchain label
value:"//reason/toolchain:bs-platform"

The toolchain to use when building this rule.

It should include both refmt, bsc and a filegroup containing the BuckleScript stdlib.

Example:

load(
    "@com_github_ostera_rules_reason//reason:def.bzl",
    "reason_module",
    "bs_module"
)

reason_module(
    name = "my_app",
    srcs = glob(["*.re", "*.rei"]),
    )

bs_module(
    visibility = ["//examples/app:__subpackages__"],
    name = "my_app.js",
    config = "//:bs_config",
    srcs = [ ":my_app" ],
    deps = [ "//examples/some/dependency" ],
    )

ocaml_native_binary and ocaml_bytecode_binary

Compile ML code into bytecode or native binaries. For bytecode binaries it will copmile them including the runtime, rather than separately. This is something that I'd like to change in the future.

Name Type Default value
name string mandatory value
A unique name for this rule, used as the name of the output binary
srcs string_list mandatory value
The ML sources of this library.
deps label_list
value:[]
Dependencies of this library, must include ReasonModuleInfo providers.
toolchain label
value:"//reason/toolchain:bs-platform"

The toolchain to use when building this rule.

It should include both ocamlc, ocamlopt, ocamldep, ocamlrun, and a filegroup containing the Ocaml stdlib.

Example:

load(
    "@com_github_ostera_rules_reason//reason:def.bzl",
    "reason_module",
    "ocaml_native_binary",
)

# BUILD file somewhere in your sources!
reason_module(
    name = "srcs",
    srcs = glob(["*.re"]),
    )

# replace native with bytecode in the rule name and you get a bytecode binary
ocaml_native_binary(
    name = "my_bin_name",
    srcs = [":srcs"],
  )

Toolchain

There is a ToolchainInfo that describes the fields required throughout the build rules to successfully compile from ReasonML down to Javascript.

Feel free to register your own toolchain or use the default toolchain that will be managed completely within Bazel.

Name Type
bsc File
The BuckleScript compiler file.
refmt File
The ReasonML Formatter file.
bs_stdlib Filegroup
A Filegroup with all the source and compiled files for the BuckleScript standard library that will be used for compiling Ocaml into Javascript
ocamlc File
The Ocaml bytecode compiler.
ocamlopt File
The Ocaml native compiler.
ocamldep File
The Ocaml dependency tool.
ocamlrun File
The Ocaml bytecode interpreter.
   
ocaml_stdlib Filegroup
A Filegroup with Ocaml standard library.

Providers

There are 2 providers included, that will carry information for the different stages of the build process.

ReasonModuleInfo

This provider is the output of the reason_module rule, and it represents a compilation unit from ReasonML to Ocaml.

Name Type
name string
The name of your the colletion of files
srcs depset(File)
A depset of all the ReasonML files that will be compiled to ML
outs depset(File)
A depset of all the target ML files that will be generated

BsModuleInfo

This provider is the output of the bs_module rule, and it represents a compilation unit from Ocaml to Javascript.

Name Type
name string
The name of your the colletion of files
srcs depset(File)
A depset of all the Ocaml files that will be compiled to Javascript
outs depset(File)
A depset of all the target ML and Js files that will be generated
deps depset(File)
A depset of all the BuckleScript modules files that the srcs depend on

MlModuleInfo

This provider is the output of the bs_module rule, and it represents a compilation unit from Ocaml to Javascript.

Name Type
name string
The name of your the colletion of files
srcs depset(File)
A depset of all the Ocaml files that will to be compiled.
outs depset(File)
A depset of all the target binary files.
deps depset(File)
A depset of all the Ocaml modules files that the srcs depend on
target "native" | "bytecode"
Whether this module is being compiled natively or as bytecode.