Crystal: Get runtime version?

Created on 21 May 2016  路  12Comments  路  Source: crystal-lang/crystal

Is there an API for getting the Crystal version? I'd like to print something like "Running with Crystal #{Crystal::VERSION}"

This kind of info is extremely useful when printing out benchmarks since system and compiler version make a huge difference.

feature compiler

Most helpful comment

It's mainly for completeness and introspection. As you said the values would also be available at compile time and might be useful in macros.

I wouldn't like to pollute the global namespace that much, and Crystal::CRYSTAL_ feels redundant. I'd vote for something akin to Ruby's RbConfig:

| Constant | Value |
| --- | --- |
| Crystal::VERSION | "0.17.3" |
| Crystal::DESCRIPTION or Crystal::FULL_VERSION | same as crystal -v |
| Crystal::BUILD_DATE | either the string used in crystal -v or maybe even a Time instance. |
| Crystal::BUILD_COMMIT | if available, else nil, preferably not abbreviated. |
| Maybe Crystal::ARCH | the architecture of the crystal binary, x86_64, i686, ... |
| Crystal::CACHE_DIR | as used by the current compiler |
| Crystal::PATH | as used by the current compiler, perhaps as Array(String) |
| Crystal::DEFAULT_PATH | compiled in default (in case currently overridden by CRYSTAL_PATH environment variable) |

Possibly more I can't think of right now.

All 12 comments

Ruby has this:

> puts RUBY_DESCRIPTION
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin15]

Workaround for now is to shell out to crystal at compile time:

p "Compiled with #{{{`crystal -v`.stringify}}}"

Funny, yesterday we were talking about this with @bcardiff

The compiler can probably pre-define a constant or two with the version, since it knows it. We need to define how to do this.

Right now if we do crystal -v it says:

Crystal 0.17.3 (Fri May 20 17:45:41 UTC 2016)

But I think I'd like the version to be just "0.17.3". So maybe we can have two constants, one for the version and one for the description. How about:

module Crystal
  VERSION = ...
  VERSION_DESCRIPTION = ...
end

But ideas for other names are welcome (they could also be CRYSTAL_VERSION, without having a module in between, not sure).

Another use case for having this is that constants can be used inside macros, so one could do:

{% if Crystal::VERSION == "0.17.3" %}
  # fix for crystal 0.17.3
{% end %}

I mentioned this somewhere before but I'd like all of the compiler's Crystal::Config exposed there too.

I think we can define constants for the output of crystal env:

$ crystal env
CRYSTAL_CACHE_DIR="/Users/asterite-manas/.cache/crystal"
CRYSTAL_PATH="/usr/local/Cellar/crystal-lang/0.17.3/src:libs"
CRYSTAL_VERSION="0.17.3"

Maybe something intuitive would be to define constants with exactly those names. But there we are missing the full version (is it important, though?).

@jhass What would you use the path and the cache dir, though? Once you compile your program that info is kind of useless or might be incorrect, if the binary is moved somewhere else.

It's mainly for completeness and introspection. As you said the values would also be available at compile time and might be useful in macros.

I wouldn't like to pollute the global namespace that much, and Crystal::CRYSTAL_ feels redundant. I'd vote for something akin to Ruby's RbConfig:

| Constant | Value |
| --- | --- |
| Crystal::VERSION | "0.17.3" |
| Crystal::DESCRIPTION or Crystal::FULL_VERSION | same as crystal -v |
| Crystal::BUILD_DATE | either the string used in crystal -v or maybe even a Time instance. |
| Crystal::BUILD_COMMIT | if available, else nil, preferably not abbreviated. |
| Maybe Crystal::ARCH | the architecture of the crystal binary, x86_64, i686, ... |
| Crystal::CACHE_DIR | as used by the current compiler |
| Crystal::PATH | as used by the current compiler, perhaps as Array(String) |
| Crystal::DEFAULT_PATH | compiled in default (in case currently overridden by CRYSTAL_PATH environment variable) |

Possibly more I can't think of right now.

It would also be nice to have the version as major, minor and patch, so that something like this can be done:

{% if Crystal::VERSION_MAJOR > 1 || (Crystal::VERSION_MAJOR == 1 && Crystal::VERSION_MINOR > 2) %}
  # Crystal 1.2 or newer
{% end %}

Or: Make Crystal::VERSION be a instance of some Version struct that defines nice comparators such that this is possible:

{% if Crystal::VERSION >= "1.2" %}
  # Same as before
{% end %}

Otherwise, it would work like a string (or just have a to_s method)

@lbguilherme One can do:

{% version = Crystal::VERSION.split(".").map(&.to_i) %}
{% if version[0] > 1 %}
{% end %}

I'd rather not add too much logic into those constants, and I prefer them to be strings. The version might even not be something separated by dots, as it can be set with an ENV variable.

I added all except Crystal::ARCH, because I don't know what's the best way to compute it. We can add it later, and probably it should also appear somewhere in Crystal::DESCRIPTION.

(I chose Crystal::DESCRIPTION instead of Crystal::FULL_VERSION because the description contains the date, the revision, etc., so it's more like a description of the crystal compiler)

Isn't the arch always the first part of the target triple: target_machine.triple.split('-').first?

There shouldn't be other means to change that. Except maybe with --cross-compile but this param may not need to take values anymore since flags are now using --target (and no longer uname).

@ysbaddaden Yes, but I don't know how to get that info at compile time, and executing another program just for this is maybe too much

Was this page helpful?
0 / 5 - 0 ratings

Related issues

malte-v picture malte-v  路  77Comments

farleyknight picture farleyknight  路  64Comments

benoist picture benoist  路  59Comments

HCLarsen picture HCLarsen  路  162Comments

stugol picture stugol  路  70Comments