Doing Crystal (3 Part Series)
Hello and welcome to another edition of Doing Crystal. In this article I’m going do a brief overview of the installation of Crystal, Crystal Shards, using the CLI, and setting up a new project.
If you haven’t yet read the first part of this series you can check it out here.
Crystal is pretty easy to install, but sometimes there are hangups. As the language has matured (remember, it is only a 5 year old language) the installation process has gotten simpler and more OS’s are now supported than before. That being said, here are some things to keep in mind:
This is probably the biggest hangup for a lot of people just getting started with Crystal. As of the writing of this article, Windows is not supported by Crystal. There are ongoing efforts to port the compiler and make compiling on Windows possible, but for now you have 2 options if you want to get started with Crystal on Windows.
- Install Linux. You can dual boot, use a VM, or just get rid of Windows all together, but Linux is definitely the best way to develop with Crystal.
- Use WSL. This is still using Linux technically, but a little easier. WSL (or the Windows Subsystem for Linux) is a native kernel compatibility layer that allows you to run real Linux inside of Windows. The one hangup here is editor support, which I tried to mitigate with my project wsl-proxy. Support for WSL has also been added to the Crystal Language plugin for VS Code.
Compiling from the source files can be quite difficult if you don’t know what you’re doing. There are several libraries that are required before you can build the compiler. On systems for which there are instructions, namely Ubuntu, Fedora, and OS X, it’s pretty easy to download and install the libraries you need, but for systems such as Arch or Alpine Linux finding the correct libraries can be a little more difficult.
Luckily help is literally a click away.
General installation instructions are located at crystal-lang.org/reference/installation.
Ruby has Bundler, NodeJS has NPM, Rust has Cargo, and Crystal has Shards. Shards is a package manager and, like Crystal itself, is still in its infancy. That being said Shards is good at what it does: fetching and installing external Crystal libraries from a git repository.
Shards should come pre-packaged with Crystal. To check if you have it installed, run
If you have shards installed and it is correctly referenced on your PATH you should see this output. The available commands are as follows:
- build — the build command checks your
shard.ymlfor binary definitions and builds them if any exist. You can use the
[targets]option to build specific targets.
- check— checks that your dependencies are up to date.
- init — generates a
shard.ymlfile in the current directory.
- install — installs dependencies listed in your
- list — lists installed shards.
- prune — removes installed shards that are no longer needed.
- update — updates shards.
- version — gets the version of a project.
Unfortunately, installing binary shards (like you can with
gem install [gemname] in Ruby) is not yet supported, but hopefully someday it will be.
The Crystal CLI is an interface to the compiler, the Crystal Playground, tools, documentation generation, test running, and more. First run
crystal --help to see if you have it installed correctly.
If you see this then you’re good to go. Let’s review the CLI’s commands.
- init— Generates a new Crystal project. You can use
crystal init lib [name]to generate a library project, or
crystal init app [name]to generate a binary project.
- build — builds a file. In most cases you’ll run
crystal build ./src/project-name.cr, where
project-name.cris the main file that was generated for you when you ran
- docs — Crystal comes with a built in documentation generator. Personally I feel like there’s a lot missing where documentation generation is concerned, but you can pretty easily generate docs using your comments and type definitions just by running
- env — prints the environment information for Crystal. ENV vars include
- eval — evaluates and runs Crystal code from the standard input.
- play — starts a local Crystal Playground server. This is somewhat like the playground located at https://play.crystal-lang.org/.
- run — builds and runs the supplied filename. Use like
crystal run [file].
- spec — builds and runs specs located in the
- tool — runs one of the available Crystal tools. Available tools are
Now that we’ve gone over the CLI a little, let’s set up a new project.
Because it’s been deemed mandatory by the coding gods, let’s create a hello world application.
First let’s open up our terminal of choice and
cd into a projects directory. In my case I’ll run
cd ~/Projects. Using the CLI, we’re going to generate a new project scaffold, and then
cd into our newly created project.
If you run
ls you should see the following output:
The important files here are
src/hello_world.cr. First let’s take a look at
I won’t go over this in detail, as most items should be self explanitory. If you need help with the available options in
shard.yml you can look at the spec here.
Let’s open our main file located at
This is the boilerplate content generated for all new Crystal projects. As you can see our project name of
hello_world has been PascalCased for the name of the base module. As a convention Crystal uses snake_case for project names, method names, variable names, etc. and PascalCase for constants such as module names and class names.
Now, as convention dictates our hello world application must print something like “Hello, World!” to the console, so let’s make it happen.
For the sake of this example we’ll be a little more verbose than we have to.
First we create a new class method in the
HelloWorld module called
say_hello. You can differentiate class and instance methods by looking for the
def self.say_hello makes a class method, where
def say_hello makes an instance method.
say_hello method takes one argument “name” which is assigned a default value of “World”. If we were to run
say_hello without any arguments the default value of “World” would be used.
Next we go outside of the
HelloWorld module to run our new method. As
say_hello is an instance method we can call it with
HelloWorld.say_hello. Class methods can not be used directly on modules as modules cannot be instantiated.
We finish things off by calling
HelloWorld.say_hello("Manas") to give a shoutout to the people at Manas Tech who created Crystal.
Let’s run our program and see the output.
The program will take a few seconds to run as it has to compile first, but you should be greeted with a “Hello, Manas!”. Congratulations! You have written your first Crystal program. Replace
build to build a binary to your current directory.
Crystal is an extremely powerful language and we’ve only scratched the surface so far. Next time we’ll discuss one of the many things that makes Crystal so powerful, it’s type system.
Please don’t forget to hit the Ego Booster button that looks like someone clapping, and if you feel so inclined share this to social media. If you share to twitter be sure to tag me at @_watzon.