LoginSignup
2
0

More than 5 years have passed since last update.

複数の環境で動作するバージョン切り替えツールのgrnenv-rsを作ってみたお話

Last updated at Posted at 2016-12-09

Groonga Advent Calendar 2016の9日目の記事です。

はじめに

GroongaはWindowsでも動かすことができます。Groongaは月ごとに新しいバージョンがリリースされるため、ある特定のバージョンを簡単にインストールして切り替えられる仕組みがあるとより便利になると感じていました。

@myokoym さんが既にWindows以外の環境に向けてgrnenv を作成されていますが、これはあくまでもbashスクリプトのため、Windowsでネイティブで動くものではなく導入の敷居が高いものとなっていました。

Windowsでのお作法

基本的にWindowsはユーザーランド(と一部カーネル空間)には高いバイナリ互換性があります。そして、Windows向けにはPortable Executables形式で提供するコマンドとすることで、ユーザーが導入する敷居を下げることができます。

Rustとは

ここではMozillaが開発しているRust言語1を用います。RustではWindowsへはPE(いわゆるexe)、macOSへはMach-O、LinuxなどにはELFバイナリとして動く実行ファイルを作成することができます。

実装

Windows編

Windows向けにはmingwによりビルドされたバイナリやインストーラーが提供されているため、こちらを引っ張ってきてインストールするようにします。
HTTPプロトコルを扱う必要があるため、Hyperと言うcrateを用いてファイルをダウンロードすることにします。

コードの一部を抜粋すると、

use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;

use hyper::Client;
use hyper::error::Error as HyperError;
use hyper::header::{Connection, UserAgent};

pub fn file_download<'a>(client: &'a Client,
                         url: &str,
                         mut base_dir: PathBuf,
                         filename: &'a str)
                         -> Result<PathBuf, HyperError> {

    let mut res = client.get(url)
        .header(Connection::close())
        .header(UserAgent(format!("grnenv-rs {}", crate_version!())))
        .send()?;
    println!("{:?}", res);
    let mut body = vec![];
    res.read_to_end(&mut body)?;
    base_dir.push(filename);
    let mut f = File::create(base_dir.to_str().unwrap()).expect("Could not create file.");
    println!("{:?}", f);
    f.write_all(&body)?;
    f.sync_data()?;
    Ok(base_dir)
}

のようなコードになります。

Rustの場合、エラーが起きる可能性のある操作を行うときにはResultというバリアントで包んで値を返すのが一般的です。

あとは、ダウンロードしてきたzipを所定の位置に展開することで、インストールが完了となります。

また、Windowsにおいてなんらかのシェルを立ち上げたときにprofileを読み込む方法を探すこととなるのですが、これはPowerShellの機能を使うことにより解決します。

PowerShellでは以下の位置にあるパワーシェルスクリプトをbashrcやzshrcと同じ要領で読み込みます。

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

macOS/Linux編

macOSやLinuxでは、ビルド済みのバイナリをそのまま使用することはパッケージ化されたものを除いて通常はできません。そのため、指定されたバージョンのソースコードをダウンロードした上でビルドしてインストールする必要があります。

その様子が install subcommand に書かれています。

指定したバージョンのGroongaを切り替えて扱うツールを作成するにあたってのプラットフォームごとの注意点を挙げました。

grnenv-rs

そうして出来上がったツールがgrnenv-rsです。

grnenv-rsはWindows 10 64bitを使う分にはコンパイル済みのバイナリをリリースページ| GitHub -- grnenv-rs からgrnenv-rs-VERSION-x86_64-pc-windows-msvc.zipをダウンロードして $Env:USERPROFILE\bin に放り込み、Visual C++ 2015再頒布可能パッケージ をインストールすることで使い始めることができます。

使い始めるには、profile.ps1 を以下の場所に配置します。

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

profile.ps1へ以下を書き込みます:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1

そして、

PS> $Env:USERPROFILE\bin\grnenv install VERSION [--arch (x86|x64)]
PS> $Env:USERPROFILE\bin\grnenv switch VERSION [--arch (x86|x64)]

として、使いたいGroongaのバージョンを指定してインストールすることができます。
その後、PowerShellを再起動します。
また、PowerShellを再起動したときに「スクリプトの実行がシステムで無効になっているため、ファイル~を読み込めません。」と言うエラーが表示された場合は、

Set-ExecutionPolicy RemoteSigned

を指定してみてください。

macOSやLinuxの場合はbashrcやzshrcにて grnenv init を実行したときに表示されるシェルスクリプトを読み込むようにします。

おまけ

このツールにはPATH環境変数の中に grnenv- のプレフィックスを持つ実行ファイルがあった場合、Rust言語のパッケージマネージャのcargoのサブコマンドの機能を真似たプロセスをまたいだプラグイン機構を載せてみています。
Windowsではexeを作成する必要があり、活用するには敷居が高いプラグイン機能ですがWindowsを考えないのであれば単に実行フラグが立っているかをみているだけなのでGroongaのバージョンの切り替えに関連するちょっとしたタスクをgrnenv-rsのプラグインにしてみるのはいかがでしょうか。

おわりに

Groongaのバージョンを手軽に切り替えるgrnenv-rsの紹介をしました。
このツールを作っている最中に遭遇したRustのTipsは色々あるのですが、ここでは作成したGroongaのバージョンを切り替えるツールについてまとめました。

WindowsとGroongaの親和性が高まっていくとよいですね。
それではWindowsでも良い全文検索を!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0