Print compile time when app starts

How can I print the compile time (format = Time.local.to_s("%Y%m%d_%H%M%S")) when the app starts ?

You mean embedding the time when the binary was built?

The macro language doesn’t expose any feature directly for this. You could run an external program (such as date) to get the current time using macro run.
Maybe the easiest way though is to pass in the current date via environment variable.

$ echo 'puts {{ env("BUILD_DATE") }}' > date.cr
$ BUILD_DATE=$(date +%Y%m%d_%H%M%S) crystal build date.cr
$ ./date
20240108_150602

Yes, I want to embedd the date at build time.

Unfortunately, I have to run my app on windows. Can this also be done with a pure crystal solution ? Without the need of a date.exe and without the need to set den ENV variable before calling crystal build.

I’ve done something similar with one of my projects. There’s a macro called “run” (I think?) That will compile and run a crystal file, and whatever the output of that crystal code is, is what the macro resolved to.

I came up with the following one. I haven’t tried it but it might work on Windows.

BUILD_TIME={{ `crystal eval 'puts Time.local.to_s("%Y%m%d_%H%M%S")'`.chomp.stringify }}
puts BUILD_TIME

I would like to know a better way too.

1 Like

With a slight adaption it works also on linux/windows:

BUILD_TIME={{ `crystal eval "puts Time.local.to_s(\\"%Y%m%d_%H%M%S\\")"`.chomp.stringify }}

Another alternative is to use macro run. It will let you compile and run a crystal program when compiling another one. Bonus point, you don’t hardcode the compiler’s binary path

# file: compile_time.cr
puts Time.local.to_s("%Y%m%d_%H%M%S")
# file: main.cr         
COMPILE_TIME = {{ run("./compile_time").stringify.strip }}

pp! COMPILE_TIME
% ./main               
COMPILE_TIME # => "20240108_152905"

I am not sure if it works in windows, but I think it should.

This is what I’ve been using for my CLI applications:

BUILD_DATE = {% if flag?(:win32) %}
               {{ `powershell.exe -NoProfile Get-Date -Format "yyyy-MM-dd"`.stringify.chomp }}
             {% else %}
               {{ `date +%F`.stringify.chomp }}
             {% end %}

Probably not the nicest looking code but it’s portable and doesn’t depend on any external files or running Crystal code during compilation.

1 Like

A question would be why you even need a time stamp from the build time, though.

Timestamps are very friendly for reproducible builds, see Timestamps — reproducible-builds.org.