Как указать путь к библиотеке (не R) для динамической загрузки библиотеки в R?

Я продолжаю получать следующую ошибку при попытке установить readxl или haven в R (обе зависимости от tidyverse) после компиляции, когда установщик запускает нагрузочный тест:

** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
  unable to load shared object '<my_lib_Path>/readxl/libs/readxl.so':
  <my_lib_path>/readxl/libs/readxl.so: undefined symbol: libiconv
Error loading failed

У меня есть libiconv.so в пути к локальной библиотеке (не для пакетов R), который включен в LD_LIBRARY_PATH, и я проверил в своем сеансе R, что Sys.getenv("LD_LIBRARY_PATH") имеет этот каталог. Почему загрузчик динамической библиотеки R не может найти этот общий объект? Есть ли другая специфичная для R переменная среды, которую мне нужно определить, чтобы загрузчик динамической библиотеки в R выполнял поиск по моему локальному пути к библиотеке?

Обратите внимание, что это не проблема с путем к библиотеке R, а проблема не-R-зависимости, которая есть у пакета R. Если бы я компилировал и связывал код C++, gcc использовал бы ld и, следовательно, LD_LIBRARY_PATH для отслеживания динамических зависимостей. Похоже, что R не соблюдает этот довольно распространенный подход, и я не могу найти никакой документации о том, как управлять этими более мелкими проблемами зависимостей.


дополнительные детали

!> sessionInfo()
 R version 3.3.3 (2017-03-06)
 Platform: x86_64-pc-linux-gnu (64-bit)
 Running under: CentOS Linux 7 (Core)

 locale:
  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8
  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
  [9] LC_ADDRESS=C               LC_TELEPHONE=C
 [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C

 attached base packages:
 [1] stats     graphics  grDevices utils     datasets  methods   base
 > 

Ранее я скомпилировал libiconv, потому что это была зависимость для чего-то другого (сейчас не помню, что — скорее всего, это не пакет R, учитывая текущие проблемы). Я попытался переустановить его, но ничего не изменилось.


Редактировать

Я также пытался вручную загрузить библиотеку перед установкой:

> dyn.load(".local/lib/libiconv.so")
> is.loaded("libiconv")
[1] TRUE
> install.packages("tidyverse")

но это не так, как указано выше.


person merv    schedule 14.07.2017    source источник
comment
Пробовали ли вы удалить readxl или haven из папки /library/ и переустановить?   -  person Mako212    schedule 15.07.2017
comment
Я не уверен, что это полезно, но, возможно, вам следует проверить вывод .libPaths()? Вы также можете использовать его для получения/установки деревьев библиотек, в которых ищутся пакеты.   -  person student    schedule 15.07.2017
comment
@Mako212 Mako212 По умолчанию R очищает (удаляет) библиотеки, которые не могут быть полностью установлены, поэтому вызов install.packages("tidyverse") всегда пытается установить readxl и haven заново.   -  person merv    schedule 15.07.2017
comment
@student Библиотека libiconv не является пакетом R и поэтому не находится в каталоге(ах) библиотеки R. Тем не менее, я попытался сделать символическую ссылку на libiconv.so в моей локальной папке библиотеки R, чтобы посмотреть, найдет ли ее там загрузчик: это не так.   -  person merv    schedule 15.07.2017
comment
Каков результат ldd /<my_lib_path>/readxl/libs/readxl.so , выполненного из R ? Может быть, это информативно.   -  person knb    schedule 17.07.2017
comment
@knb Несмотря на то, что R успешно создает readxl.so, поскольку пакет не проходит нагрузочный тест, установщик продолжает удалять все, поэтому readxl.so отсутствует. Я могу работать с.   -  person merv    schedule 17.07.2017
comment
@knb, когда я построил из исходного кода вне R, я смог сохранить src/readxl.so, хотя он и не установился, и ваше предложение оказалось очень информативным. Спасибо за помощь!   -  person merv    schedule 19.07.2017
comment
@merv рад это слышать. Я часто полагался на ldd для проверки проблем с установкой/загрузкой. Часто это помогает не прямо, а косвенно.   -  person knb    schedule 19.07.2017


Ответы (5)


Обычно метод iconv выбирается из glibc, который связан во время сборки рассматриваемых пакетов R. Однако по какой-то причине iconv в этом случае преобразуется в libiconv, но он не связывается пакетами R во время сборки.

Оригинальный обходной путь

Можно сделать ссылку на libiconv явной, добавив следующую строку в исходный файл haven/src/Makevars

PKG_LIBS=-liconv

который затем позволит вам установить из исходного кода R CMD INSTALL haven. Тем не менее, редактирование пакетов кажется хакерским, плюс это то, что нужно будет делать при каждом обновлении, что звучит как хлопотно.

Более чистый обходной путь

Другой вариант — использовать withr::with_makevars, что позволяет временно контролировать Makevars контент. С помощью этой техники можно установить прямо из репо:

withr::with_makevars(c(PKG_LIBS="-liconv"), install.packages("haven"), assignment="+=")

Кредит: @knb предложил мне проверить readxl.so с ldd, и это оказалось очень полезным, поскольку показало, что общий объект даже не пытался ссылаться на libiconv. . Зная это, я понял, что могу вручную добавить ссылку с помощью флага -liconv. Спасибо @knb!

Дополнительная информация

Что касается пакетов, соответствующие сведения о подключении библиотек к пакетам R можно найти в руководство по созданию библиотек. Что касается конфигурации системы, R- руководство администратора содержит несколько полезных разделов.

person merv    schedule 18.07.2017
comment
Это допустимый подход, особенно когда install.packages("haven") (часть системы tidyverse, зависящая от libiconv) не загружается после успешной компиляции. В некоторых случаях (включая мой) установка LD_LIBRARY_PATH или ~/.Renviron или <R_HOME>/etc/Renviron.site для включения пути к libiconv.so не устраняла ошибку Error in dyn.load. - person Samir; 25.01.2018

Вы запускаете код в RStudio Server? Если это так, ответ здесь может быть полезен.

Раньше я встречал подобную ошибку при загрузке динамической библиотеки. Библиотека находилась в пути, содержащемся в LD_LIBRARY_PATH. Когда я запускал код в консоли R, он мог правильно загрузить динамическую библиотеку. Но когда я запустил его в RStudio, возникла та же ошибка, что и в вашем посте.

Причина в том, что RStudio Server имеет собственную среду поиска библиотек. Вы должны указать следующую конфигурацию в /etc/rstudio/rserver.conf:

rsession-ld-library-path=/usr/lib64/:/usr/local/lib/:OTHER_PATH_OF_YOUR_LIB

Перезапустите RStudio Server, и ошибка должна быть исправлена.

person Shuiping Chen    schedule 21.07.2017
comment
Полезно знать, но в моем случае нет RStudio. Пока просто R через ESS. - person merv; 21.07.2017
comment
Это было очень полезно! В моем случае это была проблема с rstudio-server! Спасибо! - person Johannes Bleher; 30.01.2019
comment
У меня была бы аналогичная проблема, но оказалось, что перекомпиляция пакета, например, убежища с флагом PKG_LIBS (аналогично ответу merv), решила проблему для сервера RStudio, хотя я выполнил команду установки с помощью терминала bash из отдельного сеанса ssh и не использовал консоль Rstudio или встроенный терминал . Таким образом, я могу заставить R использовать настроенный пользователем LD_LIBRARY_PATH вместо одного, установленного сервером rstudio. - person Samir; 16.08.2019

Эти библиотеки действительно должны быть стандартными в системе на основе RH, и их можно найти.

Если вам необходимо добавить их в R, вы должны сделать это до запуска R. Один из способов — через LD_LIBRARY_PATH, лучший способ — отредактировать файл в /etc/ld.so.conf.d/ (при условии, что в RH/CentOS это тоже есть). В противном случае, возможно, через /etc/environment.

Изменить. Если /etc/ недосягаемо, вы можете делать все, что ниже $HOME. Стандартная реализация оболочки работает, и R имеет свои собственные .Rprofile и .Renviron. Вы можете иметь их ниже $HOME для всех ваших проектов и/или в каталоге для каждого проекта --- см. help(Startup).

person Dirk Eddelbuettel    schedule 21.07.2017
comment
Да, вы правы, они обычно стандартны; это нетипичная ситуация. Что касается редактирования материала в /etc/..., я нахожусь в общем кластере HPC, поэтому у меня нет прав на редактирование там. - person merv; 21.07.2017
comment
Почему мне нужно добавить библиотеки перед запуском R? Почему я не могу просто отредактировать LD_LIBRARY_PATH с помощью Sys.setenv? - person Gregor Sturm; 07.03.2018
comment
@GregorSturm в Linux невозможно эффективно изменить LD_LIBRARY_PATH запущенного процесса. - person jan-glx; 11.02.2019

Я поместил операторы export LD_LIBRARY_PATH=... в файл ~/.profile. Таким образом, и командная строка R, и RStudio Server смогут найти общую библиотеку.

В моем случае я пытался получить пакет Rglpk, чтобы найти файл libglpk.so. Согласно записи в блоге Стефана Липпена, файл .profile является предпочтительным местом для таких конфигураций, не строго связанные с bash.

person carand    schedule 06.05.2020
comment
Полезно знать, но в данном конкретном случае изменения LD_LIBRARY_PATH было недостаточно для успешной компиляции. - person merv; 07.05.2020

Вы установили R через rpm или сами скомпилировали?

решение 1

Если у вас есть разрешение на изменение исполняемого файла R (скрипт оболочки), вы можете попробовать следующее:

Изменить ~/.local/bin/R или /usr/local/bin/R или /usr/bin/R

#!/bin/bash
# Shell wrapper for R executable.

export LD_LIBRARY_PATH="<my_lib_Path>/readxl/libs/"
R_HOME_DIR=...
...
...

Решение 2

Или вы можете vim ~/.local/bin/R

#!/bin/bash
# Shell wrapper for R executable.

export LD_LIBRARY_PATH="<my_lib_Path>/readxl/libs/"

/usr/bin/R

затем добавьте ~/.local/bin к вашему PATH

person Zhuoer Dong    schedule 21.07.2017
comment
Согласно OP, у меня уже определено LD_LIBRARY_PATH (через .bashrc), и я убедился, что R правильно видит эту переменную среды во всех сеансах. Проблема в том, что устанавливаемые библиотеки не сообщают g++ ссылку на libiconv. - person merv; 21.07.2017
comment
Начиная с Ubuntu 17.04, LD_LIBRARY_PATH нельзя определить в .bashrc. Я не знал случая с CentOS. Но, возможно, все заработает после того, как вы определите LD_LIBRARY_PATH в сценарии оболочки R. - person Zhuoer Dong; 22.07.2017