オレ的「今はいったん忘れてしまいたいが記録だけはしときたい」な話。
あるアプリケーションの導入の際に2つの導入方法に誘導されたのだけれど、今々の時点で即戦力として使いたいとも思えなかったが、一度触れたことがあるのに何もメモっておかないと、あとで無駄な時間を費やすこともありそうだからメモだけはしときたい、ってそんなヤツ。というか「今 Chrome で開きっぱなしになってるそのホームページ」を閉じたいの。
見出しの通り、「パッケージマネージャ」。「あるアプリケーション」はプライベートな趣味に使うやつなのでここでは言わない。その「あるアプリケーション」が薦めていたのが、パッケージマネージャの「Scoop または Chocolatey」だった。ともに PowerShell 製になっていて、自身のインストールにも PowerShell を使う。それ自体は興味深くて、Windows 10 にとっては依存物が少なくてよかろう、と言える。
どちらもプロジェクトのゴールは同じで、端的に言い換えると「Unix におけるパッケージマネージングアプローチへの嫉妬プロジェクト」。だからともに「Windows でのパッケージマネージはユーザにとっては地獄、デベロッパにとっても地獄、ほらね、scoop ればハッピーよな」と言うことを主張している。Chocolatey のほうの「ほーらね」な熱意はよく伝わってくる。
Unix 文化においてもこれまで様々なパッケージマネージャが作られてきたし、失敗も繰り返してきている。どんなであれ、エンドユーザとしては「たった一つのパッケージマネージャにだけ依存したい」のが人情というもの。それはそうだ。「パッケージマネージャの乱立」とはこれは、一つの国内に多数の独立国が乱立しているようなものだからだ。具体的な技術では、管理に使うデータベースが色んな場所に多数存在し、それぞれ競合し合ったりする。そうはいっても Unix においてやや幸運なのは、「パッケージマネージャが Unix の思想と大喧嘩しない」ことが可能な点。「大喧嘩している」さまは Windows の方を知らないとわからないだろうが、Windows ユーザからはそれこそが「羨ましい」のだ。
Windows 文化における「パッケージの管理」の不幸は、先の例における「独立国」に相当するものが「個々のアプリケーション自身である」ことが非常に多いことである。
あるソフトウェアのデベロッパが「Unix の perl を使いたい」と考えたとする。この場合にデベロッパが採用するアプローチは大きく言えば二つに分かれ、一つには「perl をインストールしやがれ」とエンドユーザにお願いをする(あるいはインストーラからインストーラを呼び出す)。もう一つが、「自身のアプリケーションのインストールフォルダ内に、抱え込んだ perl を一緒にブっ込む」というパターン。これこそが「独立国の乱立」そのものであり、たとえば「libiconv-2.dll」があなたの Windows 内にいくつインストールされているか、一度調べてみたらいい。
Windows あるいは Microsoft の「標準」がどうであるか、というのはこれは「アプリケーション自身が抱え込め」がマナーである、ということではない。純正のものだと例えば「c:/Program Files/Common Files」に共有ライブラリを置くなど多少の慣習はある。けれども綺麗な指針があるようでないことも事実で、「抱え込み型の独立国形成型アプリケーション」が相当割合を占めている。特に Unix 生まれ、あるいは Unix 育ちのソフトウェアがこれに陥りやすい。つまり「ないようである慣習」と喧嘩する、ということだ。(わかりやすい喧嘩は「Program Files 以下ではない場所にインストールする」など。こういうのは、かなり固定された慣習が根付いた Unix ではあまり起こらない。)
つまりは「こんなんやだぁ」という反旗が Scoop と Chocolatey なのだ。と言いたいところだけど。うん、そうじゃないんだよ、そこが困る。
特に Chocolatey なんだけれど、「GUI がやだ、シンプルにマシンナリろーぜ」ばかり言ってるようにも見える。うん、まぁ確かにプログラマブルに CUI で、てのも「Unix っぽいパッケージマネージャのありがたみ」ではあるんだけどさ。一番解決したいのは、そこよりも「綺麗な管理」なわけよ。「オレ、ffmpeg 自分でインストールしてんだけど、なんでまた独自にインストールしやがんのよ、やめてよねー」てのがない一元管理ね。その意味で、Scoop と Chocolatey は実際には「新たな独立国を作る」ことにほかならない。
Scoop と決めたら Scoop だけを使い続ける、みたいなことをすればまぁいいんだろうけれど、それは「Scoop 管理下に置かれるアプリケーション群」次第。欲しいものがそこになければアウト。そして「Scoop にしかそれがない」場合、これは「Scoop 独立国から亡命させ」た方が簡単だったりする。実際ワタシはそうした:
1 [me@host: current]$ pwd
2 /c/Users/hhsprings/scoop/apps/some_app/current
3 [me@host: current]$ # scoop 国から脱北させて、MSYS 国が難民として受け入れよう:
4 [me@host: current]$ cp -pfv some_app.exe /usr/local/bin
普段から scoop 国民になろうと覚悟しない限り、つまり「/c/Users/hhsprings/scoop/」という箱庭を受け容れない限り「scoop ぱねーっ」とはならない。
つぅわけで、「Windows で Unix っぽいパッケージマネージャ」てのは、その作り手が言うほどにはオイシイ解決にはならない、と思う。気持ちは痛いほどわかるけどな…。無論、よほどこいつらが爆発的に流行してきたなら話は違ってくるけれども。
一応 MSYS, cygwin, MSYS2 などについても触れておく。
これらも実際は「独立国を作る」、つまりは scoop などと同類・同罪である。けれども、エンドユーザのマインドとして、これらと scoop たちとは決定的な違いがある。つまり「Unix という OS のエミュレーション」という独立国であるかどうか、という点。ユーザの脳内では、はっきりと「Windows と Unix」という境界が自然と出来ているので、あんまり気にならないのだ。が、scoop はその外に出て「Unix 的なものとは限らないもの」も取り込もうとし、境界を曖昧にしようとする。
結局「scoopれ!」という号令が隅々まで届くことが「約束のサンクチュアリ」だとして、「いや、それって無理な相談よ」てことなわけね、果てしな過ぎるの。
「本題のパッケージマネージャとしては」についてはまぁそんなところなんだけれど、ただ、ともに「PowerShell 製」というのがちょっと気になっていてな。最近は CPython プロジェクトが PowerShell 依存になっていたりと、もはや PowerShell がきちんと「前提となるインフラ」として認知されてきている、というのが、個人的にとても喜ばしいことだと思っている。
ワタシはこのサイトで何度も「MS DOS にしがみつくのはヤメロ、せめて PowerShell てくれ」と叫んできたけれど、正直やっぱり PowerShell って、黙殺され過ぎてきたと思ってる。かなり不幸なプロジェクトだ。Microsoft の戦略の失敗もあるんだけどね。とにかく「標準バンドル」の決断がなされてからおよそ10年くらいか、やっと今になって「少し浸透し始めた」てことだね。
まぁワタシには普段使いの Python があるので、強いて PowerShell を使う理由があまりないもんであまり活用しないんだけれど、正直「最もプア(でしかもスタンドアロン)な Windows」にとっての一番の救世主って、実は PowerShell なんだよね。.NET が提供すること全て「スクリプトで」実行出来るんだから。そういう意味で、あまり情報が充実してるとは言えない PowerShell についての「サンプルプロジェクトの一つ」としてこれらを見とくのは悪くないな、って思った。
2021-04-08追記:
最近「wget と curl のどちらとて持ってない」というシチュエーション自体がなんだか皆無になってきてるんでちょっと説得力は欠けるかもしれんけれど、「PowerShell が救世主」の一例:
1 PS C:\Users\hhsprings> $wc = New-Object system.Net.WebClient;
2 PS C:\Users\hhsprings> $contents = $wc.downloadString("https://www3.nhk.or.jp/n-data/opendata/coronavirus/nhk_news_covid19_prefectures_daily_data.csv")
3 PS C:\Users\hhsprings> $Stream = [System.IO.StreamWriter]::new('nhk_news_covid19_prefectures_daily_data.csv', $false)
4 PS C:\Users\hhsprings> try {
5 >> $Stream.Write($contents)
6 >> }
7 >> finally {
8 >> $Stream.Dispose()
9 >> }
これね、python で真面目に urllib とかでやろうとすると意外とハマってしまいがちなんだけれど、wget とかの他のツールでやるとトラブるなくできたりと拍子抜けすることが多いのよ。エラーの原因は様々な要因が絡むので一概に python だけが大変だとかってことではなくて、普段から「複数の手段」を持っておくとイザというときに助かることがある、て話。
2021-04-09追記:
「PowerShellが救世主」に関し、ひとまず「powershell cmdlet unix command equivalent」て検索で。数は多くはないけれど:
綺麗で読みやすいよね。
2021-04-11追記:
遅ればせながら Go で遊んでるんだけれど:
_golang_example_1st_.zip
この「Go環境」もなかなかに「独立国」なのね。この zip を展開して試す場合は、「echogo」のほうに cd して、「go build」「go install」。python の「setup.py 流儀」はこれは python 言語そのものに組み込まれているわけではなくて、これは後発のライブラリ(distutils)と慣習によるもの。この「流儀」が最初から組み込まれてるのが Go。install すると、Scoop とかと同じく「c:/Users/hhsprings/go/bin」の下にインストールされる(つまり「Go箱庭」)。ただし…。
Goは、二分法でいえば「コンパイル型」である。それと「ライブラリ」への依存は、「コンパイル時依存」が主、なのだと思う。実際ビルドして出来上がる実行ファイルは、(少なくともへろわるどレベルの基本的なものなら)特殊なランタイムライブラリには依存せず、Windows の場合は kernel32.dll にしか依存しないらしい。つまり「c:/Users/hhsprings/go/bin」という箱庭に押し込めるのは「ランタイム依存関係の管理」のためではないので、安全に「出国」させることが出来る。(つまり作ったバイナリを使うユーザは「Go で作られた」ことを意識してもしなくてもどちらでも良い、てこと。/go/bin の外に出せば、必然的にユーザは Go で作られたことを失念するであろう。)
この「コンパイル時依存」なのだが、C 言語で譬えるなら
1 #include "github.com/hhsprings/my_utils/my_strings.c"
のようにひと様のものを取り込むのが Go 流儀、みたいなのよね、ワタシの例で「example.com/anonnon」としてる部分は、これは Go 環境が「VCSを指している」ことを前提としてくれる。つまり、「example.com/anonnon」ではなくワタシの場合だと「github.com/hhsprings」とすれば、そして本当に github にそのレポジトリを管理するならば、Go は git で取り込んでくれる。
「OSS への参加経験のないプログラマ」はビビるかもしんない。「全世界公開」がデフォルトのこの思想は。けれども、開発に参加しないエンドユーザから見ればこれはかなり理解しやすいモデルなのではないかと思う。「ソースがどこにあるのか」がはっきりしているので、コントリビュータを呼びやすい、というメリットもあるだろう。なかなか面白い発想だよなと。単純だけど。
補足: emacs で Go を編集したければ、go-mode.el をどーぞ。取り込み方がわからない場合は、「Emacs: C Sharp Mode」参照。あと、個人的に新しい言語を学習する際にいつも最初に選んでるのがファイルのダイジェストで、それも書いたので一応お披露目とく: _golang_example_2nd_.zip