Requiring files
To make the compiler process other files you use . It accepts a single argument, a string literal, and it can come in many flavors.
Once a file is required, the compiler remembers its absolute path and later require
s of that same file will be ignored.
This looks up “filename” in the require path.
By default, the require path includes two locations:
- the
lib
directory relative to the current working directory (this is where dependencies are looked up)
These are the only places that are looked up.
The exact paths used by the compiler can be queried as crystal env CRYSTAL_PATH
:
The lookup goes like this:
- If a file named “filename.cr” is found in the require path, it is required.
- If a directory named “filename” is found and it contains a file named “filename.cr” directly underneath it, it is required.
- If a directory named “filename” is found with a directory “src” in it and it contains a file named “filename.cr” directly underneath it, it is required.
- Otherwise a compile-time error is issued.
The second rule means that in addition to having this:
you can have it like this:
which might be a bit cleaner depending on your taste.
The third rule is very convenient because of the typical directory structure of a project:
That is, inside “lib/{project}” each project’s directory exists (src
, spec
, README.md
and so on)
The fourth rule is the second rule applied to the third rule.
If you run the compiler from somewhere else, say the src
folder, lib
will not be in the path and can’t be resolved.
This looks up “filename” relative to the file containing the require expression.
The lookup goes like this:
- If a directory named “filename” is found and it contains a file named “filename.cr” directly underneath it, it is required.
- Otherwise a compile-time error is issued.
This relative is mostly used inside a project to refer to other files inside it. It is also used to refer to code from specs:
In both cases you can use nested names and they will be looked up in nested directories:
require "foo/bar/baz"
will lookup “foo/bar/baz.cr”, “foo/bar/baz/baz.cr”, “foo/src/bar/baz.cr” or “foo/src/bar/baz/baz.cr” in the require path.require "./foo/bar/baz"
will lookup “foo/bar/baz.cr” or “foo/bar/baz/baz.cr” relative to the current file.
In all of these cases you can use the special *
and **
suffixes:
- will require all “.cr” files below the “foo” directory, and below directories inside “foo”, recursively.