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.
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.
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.