RでCRANからパッケージをダウンロードする関数としてdownload.packages()
がある。
この関数はダウンロードするパッケージの形式(ソースパッケージかバイナリパッケージかは)をtype
引数で指定することができる。
環境ごとの設定によるが基本的には指定しないとソースパッケージがダウンロードされる。
download.packages("xfun", ".") #> [,1] [,2] #> [1,] "xfun" "./xfun_0.49.tar.gz"
バイナリパッケージをダウンロードしたかったら、type
引数に"binary"
とするとWindowsで実行していると、Windows用のバイナリパッケージ(.zip
)がダウンロードできる。Windows環境でmacOS用のバイナリパッケージ(.tgz
)をダウンロードしたかったら"mac.binary.big-sur-arm64"
などと指定すると環境によらず指定した環境向けのバイナリパッケージがダウンロードできる。
ドキュメントにはmacOS用のバイナリパッケージをダウンロードするには"mac.binary"
でいいと書いているが、現状ではこれではうまくいかない。この点については過去記事の通り。
……なのだが、ここでtype
引数だけを指定してもうまくダウンロードできな事例に時折遭遇する。
例えば、先に上げたxfun
パッケージなどはWindows環境(x86_64環境)のRからmacOS用のバイナリパッケージをダウンロードしようとすると次の用にうまくダウンロードできないという事例に遭遇する。
download.packages("xfun", ".", type = "mac.binary.big-sur-arm64") #> Warning in download.packages("xfun", ".", type = "mac.binary.big-sur-arm64"): #> no package 'xfun' at the repositories #> [,1] [,2]
CRANリポジトリ上に確かにxfun
パッケージが存在するし、macOS用バイナリパッケージも存在するのに、なぜ、となってしまう。これはxfun
パッケージ以外にも複数のパッケージで同様の事例が発生する。これを解決する方法のメモ。
まずは解決策を示すが、単回でよければ次のようにavailable = available.packages(type = "mac.binary.big-sur-arm64", filters = list())
と指定するとダウンロードできる。
download.packages("xfun", ".", available = available.packages(type = "mac.binary.big-sur-arm64", filters = list()), type = "mac.binary.big-sur-arm64") #> [,1] [,2] #> [1,] "xfun" "./xfun_0.49.tgz"
ここでの、available.packages()
内のtype
はdownload.packages()
関数で指定するtype
でしていするものと同じである必要がある(mac.binary.big-sur-x86_64なら両方そうする)。
これはdonwload.packages()
関数がリポジトリのパッケージリストやリポジトリのURLを参照するための関数である、available.packages()
関数の挙動に関連するものとなっている。
available.packages()
はその関数の名の通り、CRANリポジトリ上にあるすべてのパッケージのリストを返すのではなく利用可能なパッケージのリストを返してくれる。つまり、デフォルトでは利用中の環境(OSやアーキテクチャなど)で利用可能かをフィルターしてリストを返すという挙動をしてくれている。このavailable.packages()
関数はinstall.packages()
でインストールするためのパッケージをダウンロードするために使われており、インストールする環境で使えないパッケージのリストを返してもらっても普通は困るので都合がいいので既定の挙動はこれでいいのだが、OSやアーキテクチャなどの環境の異なるRのためにパッケージをダウンロードする場合にはこの仕様は都合が悪くなる。
そこでavailable.packages()
がリストをフィルターするfilters
引数を調整するといいだろうということになる。filters
引数の既定値がNULL
となっておりここで、filters
引数がNULL
の場合には既定値ではc("R_version", "OS_type", "subarch", "duplicates")
がフィルターの項目になている。特になにもフィルターしないようにするにはlist()
などとする必要がある。重複項目を除く"duplicates"
でもいい。多くの場合は悪さをしているのは"OS_type"
と"subarch"
なのでここをフィルターから除ければ問題ない。
ということで一旦解決。
複数パッケージをダウンロードする必要があるとき(例えばminiCRAN
パッケージなど)にはもう少し別のアプローチが有用となる。
特に、miniCRAN
は現在CRAN上で公開されている0.3.0ではfilters
引数を指定することができないので、下記の対応をするほかない。github上で開発中の次期0.3.1ではmakeRepo()
関数でfilters
引数を指定できるようになるので上記のようにfilters = list()
でも対応できるようになると思う。
もう少し詳しくavailable.packages()
関数の挙動やドキュメントをみるとfilters
引数がNULL
のときのフィルターの項目はgetOption("available_packages_filters")
で参照され、ここが指定されずNULL
である場合にc("R_version", "OS_type", "subarch", "duplicates")
がフィルターの項目になっていると分かる(utils:::available_packages_filters_default
が呼び出されている)。
つまり、options(available_packages_filters = "duplicates")
やoptions(available_packages_filters = list())
などと事前に指定するとdownload.packages("xfun", ".", type = "mac.binary.big-sur-arm64")
でもダウンロードできるようになる。
options(available_packages_filters = list()) download.packages("xfun", ".", type = "mac.binary.big-sur-arm64") #> [,1] [,2] #> [1,] "xfun" "./xfun_0.49.tgz"
そのため、miniCRAN
パッケージでmakeRepo()
やaddPackage()
を実行する前にoptions(available_packages_filters = "duplicates")
などと指定してダウンロードできないバイナリパッケージがなくなり解決となる。
miniCRAN
パッケージをつかってローカルリポジトリを作成するときに少しハマったのでメモしておく。