Help us understand the problem. What is going on with this article?

Nimbleファイルのバージョン情報をソースに埋め込む

More than 1 year has passed since last update.

概要

追記:2018/12/24
最終的には @flat_leon さんのコメントの方式にしました。
気になる方はコメントへジャンプ!!

以下、読み物としてどうぞ。

Nimbleファイルのバージョン情報をstaticExecを使って、ソースに埋め込みます。

コンパイル時実行

Nimにはコンパイル時に実行するstaticRead/staticExecという機能があるそうで、@2vgさんのこちらの記事(Nimでコンパイルタイム実行を使用してみる)を読んで初めて知りました。

リリース時のミス

ちょうど私のNimで作っているツールのバージョンをアップしようと、Nimbleファイルに記述しているバージョン番号を変更したところ、ツール内で利用しているコマンドラインパーサー(docopt)に渡しているバージョン番号と合っていないという状態になりました。

sample.nimble
srcDir  = "src"         # ソースフォルダ
version = "0.2.0"       # バージョン情報
main.nim
import docopt

let doc = """
application

Usage:
  application (-v | --version)

Options:
  -v --version  Show version. 
"""

# docoptの初期化はバージョンを渡す必要があり、nimbleのversionと合っていない
let args = docopt(doc, version = "application 0.1.0")

コンパイル実行時にnimbleファイルを読んでしまえ

で、冒頭の記事にてstaticExecを使って、コンパイル時に自動でソースにバージョン情報を埋め込んでしまおうというのが今回の内容となります。

ディレクトリ構成は以下を想定します。
utilディレクトリはビルド対象外フォルダとしています。

C:.
|   application.nimble   <= nimbleファイル。バージョンが記述されている
+---src
|   main.nim             <= バージョンを表示したいモジュール
|   version.nim          <= バージョンを埋め込むソース
\---util
    get_version.nim      <= application.nimbleからバージョンを抜き出す
main.nim
import version    # バージョン情報が埋め込まれたソース

# version.nimでexportされたcurrent_versionをバージョン情報として渡す
let args = docopt(doc, version = "application " & version.current_version)
src/version.nim
# staticExecで、util/get_version.nimを実行した結果を埋め込む
const current_version* = staticExec(
  "nim c -r --hints:off --verbosity:0 -o:../bin/test ../util/get_version.nim application")

バージョン埋め込みがリリース時のみで良いなら、以下のようにすれば、ビルドのたびにバージョン読み込みしなくても良いかもしれません。

src/version.nim
when defined(release):
  # staticExecで、util/get_version.nimを実行した結果を埋め込む
  const current_version* = staticExec(
    "nim c -r --hints:off --verbosity:0 -o:../bin/test ../util/get_version.nim application")
else:
  const current_version* = "X.X.X"

nimbleファイルからバージョンを取得

util/get_version.nim
import os
import nre, options, strutils
import strformat

# 引数を取得
let 
  cmdArgs = os.commandLineParams()
  pkgName = cmdArgs[0]

# XXXX.nimbleを読んで、version = X.X.X の X.X.Xを抜き出して、表示する
let f = open(fmt"../{pkgName}.nimble", FileMode.fmRead)
let lines = f.readAll().split("\n")
for line in lines:
  let mOpt = line.match(re"(version)\s*=\s+""(\d+\.\d+\.\d+)""")
  if mOpt.isSome:
    let m = mOpt.get
    echo m.captures[1]
    break
f.close

まとめ

  • staticExecを使って、Nimbleファイルに記述されたバージョン番号をソースに埋め込むことができました。
  • staticReadというメソッドもあり、ファイルの内容を埋め込んでしまうこともできるみたいです。
  • なんでもありなNimが大好きです。
6in
窓際エンジニアです
future
ITを武器とした課題解決型のコンサルティングサービスを提供します
http://future-architect.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした