R on OpenBSD
install R
どういう訳かこの所ずっとリナ系にべったり。OpenBSDはさっぱりかまって貰えないで泣いている。ならば、Rの一番新しいのでも入れてみようか。
と始めてみたものの configure で、fortranが見つからないんですけどって言われて、先に進むのを拒まれてしまった。
じゃフォートランを入れればいいんだな。パッケージになってるのは、flang ってやつ。能書きには、
Flang is a Fortran compiler targeting LLVM. This package includes the compiler passes and runtime library. Flang is based on the Nvidia PGI Fortran compiler.
LLVM系なのね。取り合えず入れてみたけど、GNU R にはお気に召さないようで、全く無視されてしまったわい。あくまでgccですかい! なんたって、コンパイラー・コレクションですから、老舗ですから。
だったら、OpenBSDのパッケージになってるRはどうしてるの? Makefileを覗くと
COMPILER = base-clang ports-gcc base-gcc
と、コンパイラーの揃い踏みを要求。どうも使ってるのは、
MODFORTRAN_COMPILER = gfortran
モジュール用途みたい。
面倒嫌いなオイラーは、素直にパッケージから入れる事にした。
doas pkg_add R quirks-3.326 signed on 2020-09-22T20:03:15Z R-3.6.3:gtar-1.32p1: ok R-3.6.3:g95-8.3.0p5: ok R-3.6.3:texlive_mktexlsr-2019: ok R-3.6.3:texlive_texmf-buildset-2019: ok R-3.6.3:texlive_synctex-2019: ok R-3.6.3:potrace-1.16: ok R-3.6.3:ffcall-1.10p5: ok R-3.6.3:clisp-2.49p5: ok R-3.6.3:detex-2.8.1: ok R-3.6.3:zziplib-0.13.62p1: ok R-3.6.3:harfbuzz-icu-2.6.5: ok R-3.6.3:gdbm-1.18.1p0: ok R-3.6.3:libdaemon-0.14p1: ok R-3.6.3:libevent-2.1.11: ok R-3.6.3:dbus-daemon-launch-helper-1.12.16p2: ok R-3.6.3:avahi-0.8: ok R-3.6.3:cups-libs-2.3.3: ok R-3.6.3:ghostscript-fonts-8.11p3: ok R-3.6.3:ijs-0.35p3: ok R-3.6.3:jbig2dec-0.11: ok R-3.6.3:ghostscript-9.07p7: ok R-3.6.3:ps2eps-1.68p0: ok R-3.6.3:p5-IPC-Run3-0.048: ok R-3.6.3:libpaper-1.1.28: ok R-3.6.3:psutils-2.03p0: ok R-3.6.3:t1utils-1.41p0: ok R-3.6.3:dvi2tty-5.3.1p0: ok R-3.6.3:texlive_base-2019p0: ok R-3.6.3:texinfo-6.5p4: ok R-3.6.3:zip-3.0p1: ok R-3.6.3: ok Running tags: ok The following new rcscripts were installed: /etc/rc.d/avahi_daemon /etc/rc.d/ava hi_dnsconfd See rcctl(8) for details. New and changed readme(s): /usr/local/share/doc/pkg-readmes/R /usr/local/share/doc/pkg-readmes/avahi /usr/local/share/doc/pkg-readmes/texlive_base --- +ghostscript-fonts-8.11p3 ------------------- You may wish to update your font path for /usr/local/share/fonts/ghostscript
なんで、こんなのが入って来るのってpkgも名を連ねている。 その筆頭はg95って怪しいやつ。大体想像が付くけど、中身を確認しとく。
ob$ egfortran -v Using built-in specs. COLLECT_GCC=egfortran COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-openbsd6.7/8.3.0/lto-w rapper Target: x86_64-unknown-openbsd6.7 Configured with: /usr/obj/ports/gcc-8.3.0/gcc-8.3.0/configure ...
こんなのを自前でコンパイルしてたら、日が暮れちゃうぞと。まあ、フォートランが手に入ったんで、最新のRもスラスラとコンパイル出来るかな。gcc-8.3 は、パッケージ名で、実体は、egccになってるな。egdbと言い、GNUの拡張は、頭にeを付けるのがOpenBSDの掟なのか。
install.packages
R は入ったけど、裸のそれではほとんど使い道が無いだろう。ってか、前回の最後に記載した、tidyverseの実習をやってみたかったのよ。
debinanに入れたそれでは、データの形式を整えるところから始めよう。マーケターが1からRを勉強します【第3回】
に出て来る、 pivot_longer
と pivot_wider
が使えなかったんだ。
調べてみると、【tidyr】gather?, spread? もう古い。時代はpivot
に、行き着いたんだ。
設計ミスが有ったんで、新しいリリースで修正したとな。まるでpython2 -> python3 みたいな遍歴な訳ね。だったら今後の事も有るんで、CRANから入れてみましょ(debianな時は、面倒なのでaptで入れてた)。
素から入れたら、どんな負荷がかかるかも確認出来るからね。Windowsとかだとユーザーが多いので、多分バイナリでの提供だろうけど、辺境のOSであるOpenBSDでは、望むべきでは無い。
一般ユーザーでRを起動して install.package しちゃうと、/usr/local/lib/R/ 以下に書き込み権限が無いので、自HOMEに入っちゃう。これを嫌って、doas R で起動した環境から試してみる。
お試しで簡単そうな install.package('hms') を試した。最初にどこのCRANを使うねんって質問が出てきたので、リストからJapanを選択。簡単に入ったな。余勢を駆って、tidyrとかを入れる。
> install.packages('tidyr') also installing the dependency 'cpp11' trying URL 'https://cran.ism.ac.jp/src/contrib/cpp11_0.2.1.tar.gz' Content type 'application/x-gzip' length 198184 bytes (193 KB) ================================================== downloaded 193 KB trying URL 'https://cran.ism.ac.jp/src/contrib/tidyr_1.1.2.tar.gz' Content type 'application/x-gzip' length 881544 bytes (860 KB) ================================================== downloaded 860 KB * installing *source* package 'cpp11' ... ** package 'cpp11' successfully unpacked and MD5 sums checked ** using staged installation ** R ** inst ** byte-compile and prepare package for lazy loading : * installing *source* package 'tidyr' ... ** package 'tidyr' successfully unpacked and MD5 sums checked ** using staged installation ** libs c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -I"/usr/local/lib/R/library/cpp11/include" -I/usr/local/include -fpic -O2 -pipe -c cpp11.cpp -o cpp11.o : DONE (tidyr) The downloaded source packages are in '/tmp/Rtmp0VdCtd/downloaded_packages' Updating HTML index of packages in '.Library' Making 'packages.html' ... done
clangが普通に使われているな。それから、/tmpの下にDLしたソースが残っている。Rを終了しちゃうと消えてしまうので、必要ならバックアップしておこう。
ob$ ls Rtmp0VdCtd/downloaded_packages/ R6_2.4.1.tar.gz fansi_0.4.1.tar.gz purrr_0.3.4.tar.gz assertthat_0.2.1.tar.gz generics_0.0.2.tar.gz rlang_0.4.7.tar.gz cli_2.0.2.tar.gz glue_1.4.2.tar.gz tibble_3.0.3.tar.gz cpp11_0.2.1.tar.gz hms_0.5.3.tar.gz tidyr_1.1.2.tar.gz crayon_1.3.4.tar.gz lifecycle_0.2.0.tar.gz tidyselect_1.1.0.tar.gz digest_0.6.25.tar.gz magrittr_1.5.tar.gz utf8_1.1.4.tar.gz dplyr_1.0.2.tar.gz pillar_1.4.6.tar.gz vctrs_0.3.4.tar.gz ellipsis_0.3.1.tar.gz pkgconfig_2.0.3.tar.gz
これ、hms,tidyr,dplyrをインストールした時に、お取り寄せされたもの。ggplot2とかは、使いこなせていないので、まだ入れていない。気が向いたら、そのうちに。
ess
emacsにessでも入れておくか。最新のessは補完もばっちりらしい。 companyとuse-package(init.el用)を取り寄せ。
(use-package company :config (global-company-mode) (setq company-idle-delay 0.1 company-minimum-prefix-length 3 company-selection-wrap-around t) (bind-keys :map company-mode-map ("C-i" . company-complete)) (bind-keys :map company-active-map ("C-n" . company-select-next) ("C-p" . company-select-previous) ("C-s" . company-search-words-regexp)) (bind-keys :map company-search-map ("C-n" . company-select-next) ("C-p" . company-select-previous)))
こんな設定をする。後はemacs hoge.R して、Rを動かしておけば、essとRが連携して、補完が出来るようになる。色々なemacsの設定例を見てきたけど、これに言及してるのは無かった。世間の常識なんで、誰も触れていないのかな。
; (global-company-mode) (add-hook 'ess-mode-hook 'company-mode) (add-hook 'inferior-ess-mode-hook 'company-mode)
なお、R関係だけで補完させたいなら、上記のように修正する。ess-mode-hockは、編集バッファーで有効、inferior-..の方は、Rのプロンプトが有る方での有効化だ。
ちょいと余談になるけど、特定なmodeでcompanyを有効にする方法、すぐに使おうと思った訳ではない。最初はどこでもcompanyしてたんだ。所がそれだと、emacs+gdbの時に使い難いったらありゃしない。そんな訳で、探したのさ。そしたらpythonの例が見つかったので、それをessに適用したって訳。問題はRのプロンプト側。statusラインには、iESSってモードが出てたんで、素直にそれを設定。ダメであった。
で、オイラーは、Rのコンソール側で、C-h m して、emacs君に問い合わせ。なんて言うのが正式名称かとね。
iESS mode defined in ‘ess-r-mode.el’: Major mode for interacting with inferior R processes. In addition to any hooks its parent mode ‘inferior-ess-mode’ might have run, this mode runs the hook ‘inferior-ess-r-mode-hook’, as the final or penultimate step during initialization.
こんな具合に出てきたのでそれを設定。ぐぐると結論だけが書いてあるけど、それをコピペするだけじゃ発展性が無い。で、あえて書いてみた次第。
ob$ ps a : 56516 p2 S+ 0:08.25 emacs hoge.R (emacs-26.3) 63690 p3 S+ 0:01.14 /usr/local/lib/R/bin/exec/R --no-readline
これを見ると、R側での補完を殺しておいて、都度emacs側から補完情報を問い合わせている事が分かる。
後はお好みで、装飾をすれば良い。
(custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(default ((t (:family "DejaVu Sans Mono" :foundry "PfEd" :slant normal :weight normal :height 136 :width normal)))) '(company-preview ((t (:foreground "darkgray" :underline t)))) '(company-preview-common ((t (:inherit company-preview)))) '(company-tooltip ((t (:background "lightgray" :foreground "black")))) '(company-tooltip-common ((((type x)) (:inherit company-tooltip :weight bold)) (t (:inherit company-tooltip)))) '(company-tooltip-common-selection ((((type x)) (:inherit company-tooltip-selection :weight bold)) (t (:inherit company-tooltip-selection)))) '(company-tooltip-selection ((t (:background "blue" :foreground "white")))))
tofu
グラフを書くと、文字が豆腐になる。ちゃんと日本語に設定してないからかと思ったけど、そうでは無いようだ。オイラーに取っては、フォントと印刷は鬼門だからなあ。 でぐぐる。
なんだか、こんな設定をすると、ちゃんと表示した。
> par(family="Console") > plot(1:10 ~ c(1:10) ) > curve(sin, -10, 10)
一度、グラフの窓を出したままにしておくと、豆腐文字は避けられる。窓を消してしまうと、元に戻ってしまう。
compile R
フォーフォー・フォートラン・ラン・ランも手に入った事だし、R 4.0.2でも自前で作ってみるか、ってなもんで、configure したんだけど、思わぬ伏兵が。
checking zlib.h usability... yes checking zlib.h presence... yes checking for zlib.h... yes checking if zlib version >= 1.2.5... no checking whether zlib support suffices... configure: error: zlib library and headers are required
なんと、基幹のzlibが古いとよ。どうしろと? config.log惨状もとえ参照。
configure:45212: checking zlib.h presence configure:45212: gcc -E -I/usr/local/include conftest.c configure:45212: $? = 0 configure:45212: result: yes configure:45212: checking for zlib.h configure:45212: result: yes configure:45222: checking if zlib version >= 1.2.5 configure:45248: gcc -o conftest -g -O2 -I/usr/local/include -L/usr/local/lib conftest.c -lm -liconv -licuuc -licui18n >&5 configure:45248: $? = 0 configure:45248: ./conftest configure:45248: $? = 1
/usr/local/側にある奴って、古いのか。
ob$ ldd /usr/local/lib/R/bin/exec/R | grep z 0000080e67dab000 0000080e67dd9000 rlib 0 1 0 /usr/local/lib/liblzma.so.2.1 0000080e89d79000 0000080e89d8f000 rlib 0 1 0 /usr/local/lib/libbz2.so.10.4 0000080e7f813000 0000080e7f82e000 rlib 0 2 0 /usr/lib/libz.so.5.0
pkgから入れたやつは、/usr/lib側のやつが使われている。どんなマジックを使ってるのかな? port/math/R のエリアをうろうろ。パッチが有るな。ドンピシャパッチが用意されてた。 核心部分は、
- if (ZLIB_VERNUM < 0x1250) { + if (ZLIB_VERNUM < 0x1230) {
ちょっと古いやつでもOkさせてよだ。
cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> #include <string.h> #include <zlib.h> int main() { #ifdef ZLIB_VERNUM if (ZLIB_VERNUM < 0x1250) { exit(1); } exit(0); #else exit(1); #endif } _ACEOF
ここまで分かれば、後はやるだけーーー。
ob$ ./configure --prefix=/home/sakae/MINE : ob$ time gmake -j3 : building/updating vignettes for package 'utils' ... gmake[1]: Leaving directory '/home/sakae/src/R-4.0.2/src/library' 10m00.54s real 9m25.27s user 9m44.43s system ob$ gmake install
後はおまけでinfoだな。
ob$ gmake info gmake[1]: Entering directory '/home/sakae/src/R-4.0.2/doc' gmake[2]: Entering directory '/home/sakae/src/R-4.0.2/doc/manual' ERROR: 'texi2any' v5.1 or later needed but missing on your system.
残念ながら余のシステムには、そんなコマンド無かったわい。これは諦めだな。
期待してた、グラフを書いた時のtofuは、相変わらず駄目であった。未来永劫 par(…) しなきゃならんかのう。まあ、オイラーの所は特殊で、X関係の表示はWindows側に投げているんで、そのせいかも知れないけど(推定無罪ってことか)。
i386なOpenBSDでもtofuが出て来る。MobaXtermなX環境でもtofuが出て来る。OpenBSDの自前のXで試そうとしたら、VMwareでもvboxでもstartxでエラーになる。昔はちゃんと動いていたのに、、、何でだ?
Sys.getenv
ふと、Makeconfなんてファイルを見ていたんだ。(@debian /etc/R/Makeconf)。そしたら、やたらめったら、configure時に色々指定してたぞ。オイラーは、–prefix だけだったのとは大違い(少しは反省しろよ)。下記のように、頭にRが付く大文字のやつが指定されてた。これって、環境変数の埋め込みではなかろうか?
'R_PAPERSIZE=letter' 'R_SHELL=/bin/bash'
ちょいと炙り出ししてみるか(ソースが有ると、こういう楽しみが有る)。
sakae@pen:~/src/R$ find . -type f | xargs grep R_PAPERSIZE : ./library/profile/Rprofile.unix:papersize <- Sys.getenv("R_PAPERSIZE_USER") ./library/profile/Rprofile.unix: else Sys.getenv("R_PAPERSIZE")
他にどんな環境変数が有るか(どのマニュアルに書いてあるか? 探すよりソース嫁)
sakae@pen:~/src/R$ find . -type f | xargs grep -h 'Sys.getenv("R_' | sed 's/.*\("R.*"\))*/\1/' | sort | uniq "R", "R_ARCH" "R_ARCH", "R_ARCH", NA_character_) "R_ARCH" # unix only "R_ARCH") == "/x64" && "R_AVAILABLE_PACKAGES_CACHE_CONTROL_MAX_AGE", "3600" "R_BATCH" {
ちょいと絞り込みが甘いけど、点検するには十分か。それにしても、色々有るなあ。期待してたフォントファミリー関係は、見当たらず。
悔しいのでちゃんと点検しよう。 文字列の置換・抽出・検索と正規表現 を参考にするのが良いだろうけど、注意しないとGNUに毒されてしまう。よって、OpenBSDにて確認する。
find . -type f | xargs grep -h 'Sys.getenv("R_' | sed 's/.*"\(R_[^"]*\)".*/\1/' | sort | uniq | wc
R 4.0.2 で確認したら74個も検出されたぞ。どれだけ有るんや。これでも絞って、頭がRで始まる物だけにしたけど、頭が _ で始まるものも有るからなあ。
R_AVAILABLE_PACKAGES_CACHE_CONTROL_MAX_AGE R_ENABLE_JIT
誰が使うんだと言うような長ったらしいやつが有るかと思えば、興味を引くやつも有るなあ。
上の検索で、有名な R_HOME
が出てきていなかった。何でかなと思ったら、
> Sys.getenv(c("R_HOME", "R_PAPERSIZE", "R_PRINTCMD", "HOST")) R_HOME R_PAPERSIZE R_PRINTCMD HOST "/usr/lib/R" "letter" "/usr/bin/lpr" ""
ベクターで欲しいものを渡して、一気に取り出してしまう荒技を使ってたぞ。なかなかRらしくて、笑って許したる。結果をxに受けておいて、表現を確認すると
> str(x) Named chr [1:4] "/usr/lib/R" "letter" "/usr/bin/lpr" "" - attr(*, "names")= chr [1:4] "R_HOME" "R_PAPERSIZE" "R_PRINTCMD" "HOST" > x[1] R_HOME "/usr/lib/R" > x["R_HOME"] R_HOME "/usr/lib/R"
awkも真っ青な連想配列になってる。
上のSys.getenv()は何処に載ってるかと言うと、なんとmanの中のexampleだった。本体系には表れていないので、ユーザーの便に供するものだな。Sys. して、展開してみると、結構面白いのが載ってる。例えば、Sys.info()。OSのバージョンとかが得られるので、何かの時に役に立つかも知れないし、全くの無駄知識かも知れない。
正規表現をgg(ぐぐる)してたら、面白いものに行き当たった。 シェルスクリプトはバイナリを扱えない。さてどうしよう こういうの、オイラー大好物。瓢箪から駒である。
par
> trace(par) > par(family='console') trace: par(family = "console") > curve(sin, -4,4) trace: par("pch") trace: par("lty") trace: par("col") trace: par("lwd") trace: par("ann")
ふーん。