Search code examples
compile-timecrystal-lang

Run arbitrary code at compile time


I know that Crystal has its macro system for defining code at compile time but is it possible to run code apart from that?

For example, can we do this so that it runs during compilation?

puts "foobar"

Or for a more serious example, can we read from and write to the file system where the compiler is running?


Solution

  • Yes we can! With the help of the run macro method or the system macro method.

    Let's have an example that compiles a random greeting into the program each time it is build:

    greetings.txt:

    Hello
    Hey
    Hi
    

    greeting.cr:

    puts File.read_lines("#{__DIR__}/greetings.txt").sample
    

    greeter.cr:

    puts {{run("./greeting").stringify}}
    

    Compile with crystal build greeter.cr, you'll notice that the output stays the same for the compiled binary but is random for each time your recompile it.