crystalコマンドでハマった罠
最初に
正直、Crystalで大きめなコードをまだほぼ書いたことがなく、
ブラウザでCrystalを書いて実行することも多く、
crystal
コマンドについてあまり理解しておらず、ちょっとハマったことを書く。
最初にcrystalコマンドの説明を見てみる
多くのコマンドがそうであるようにcrysltal --help
とすれば、
crystal
コマンドの簡単な説明を得ることができる。
crystal -h
やcrystal help
でもよい。
$ crystal --help Usage: crystal [command] [switches] [program file] [--] [arguments] Command: init generate a new project build build an executable docs generate documentation env print Crystal environment information eval eval code from args or standard input play starts Crystal playground server run (default) build and run program spec build and run specs (in spec directory) tool run a tool help, --help, -h show this help version, --version, -v show version Run a command followed by --help to see command specific information, ex: crystal <command> --help
これを見ると、それぞれのコマンドの説明が見れる。
「run (default)」と書いてあり、サブコマンドを省略するとrun
が適用されるようにみえる。
しかし、これには罠があり、省略するとオプションの扱いが変わってくるので全く同じではない。
なお、このhelpの説明を見ると、「crystal
crystal run --help
の形でサブコマンドのもう少し詳しい説明を読むことができる。
コンパイラの使い方 - Crystal
なお、日本で詳しい説明を見たければ、上記のページを見ればよさそう。
runコマンドの有無の違い
crystal run foo.cr --release crystal foo.cr --release
自分は、上と下が同じだと思って罠にハマった。
上のrunコマンドで呼び出した場合は、--releaseオプションが機能する。
しかし、下の場合は、--releaseオプションが機能しなかった。
これについて、CrystalコミュニティのDiscordで雑に尋ねてみたところ、
z64さんという方に「昔はrunコマンドなしで、--releaseオプションが機能した」と教えてもらった。
なぜ削除したのか質問してみたが、正確に覚えてないとのことだった。
ただcrystal foo.cr --releaseの場合は、crystalコマンドのオプションではなく、ファイルのオプションとして認識されるということだった。
{% if flag?(:release) %} puts ["flag release", ARGV] {% else %} puts ["flag no release", ARGV] {% end %}
上記の内容のファイルを作り、比べてみると分かりやすい。
ここでは、foo.crというファイル名にした。
$ crystal run foo.cr --release ["flag release", []] $ crystal foo.cr --release ["flag no release", ["--release"]]
runコマンドの方は、crystalコマンドのオプションとして--releaseが認識されていてflag?
マクロで認識できるがARGVには残っていない。
対して、runを省略した場合は、crystalコマンドのオプションとして認識されずARGVに残る。
というわけで、上記のような違いがあった。
まとめ
最初はrun省略時に何も認識されてないように見えて修正されるべきバグか何かだと思ったが、
聞いてみるとファイルのオプションとして認識されているとのことだった。
初見殺しな感じもしてわかりにくい気もするが、何か使い分けできるかもしれないので、もしかしたら便利かもしれない。