Моя динамическая библиотека успешно создана с зависимостями от библиотек наддува, которые были созданы и установлены с пользовательским префиксом (./b2 install --prefix=PREFIX
). Тем не менее, когда я бегу otool -L
в моей библиотеке я получаю вывод, как это:
...
libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
...
Который, в отличие от других зависимостей, представлен без полного пути к этим библиотекам повышения. Это приводит к ошибкам во время выполнения, когда моя библиотека загружается приложениями.
Я знаю, что можно использовать install_name_tool
чтобы вручную решить эту проблему. Тем не менее, я пытаюсь понять, почему это происходит только для библиотек boost и не происходит с другими зависимостями, от которых зависит моя библиотека?
РЕДАКТИРОВАТЬ
Меня попросили привести пример команды сборки, но, как обычно, пример «реальной жизни» немного сложнее.
В моем случае есть библиотека libA.dylib
который зависит от повышения. Тогда есть моя библиотека libMy.dylib
который зависит от libA.dylib
и повысить также. Проблема возникает во время configure
шаг, когда выполняется простая проверка существования библиотеки (пользовательская тестовая программа похожа на AC_CHECK_LIB
). Эта проверка пытается создать небольшую тестовую программу, которая связана с libA.dylib
для того, чтобы доказать наличие libA.dylib
и это терпит неудачу — из-за ошибки не в состоянии найти библиотеки повышения. Конечно, он не найдет их, потому что otool -L libA.dylib
дает мне бодрость без полного пути.
Чтобы ответить на вопрос:
«Почему это происходит только для библиотек boost и не происходит с другими зависимостями, от которых зависит моя библиотека?»
Техническая причина в том, что система сборки Boost (bjam) явно назначает установить имя библиотеки, чтобы быть только именем файла. Это может быть сделано внутри, используя -install_name опция компилятора.
Для обоснования этого я не могу говорить за разработчиков Boost, поэтому я мог только предполагать (что является плохой формой инвестиций): жесткое программирование локального пути установки в библиотеке только задерживает ошибку времени выполнения «библиотека не найдена» для время распространения, чтобы они могли просто попросить вас правильно решить его, как только время разработки. (Или это может быть просто наследственное поведение, которое они не хотели тратить больше времени на переделки;)
Давайте представим, что ваша динамическая библиотека (которая зависит от Boost) называется myLib
, Как вы уже указали в своем вопросе, вы вполне могли бы изменить имя установки для библиотек Boost, записанных в myLib
:
install_name_tool myLib -change libboost_regex.dylib /full/path/to/libboost_regex.dylib
Альтернативой является изменение имени установки самих библиотек Boost:
install_name_tool libboost_regex.dylib -id $new_name
При таком подходе имя установки $new_name
теперь будет записан в myLib
когда вы строите его против модифицированного libboost_regex.dylib
Вы знаете, нужно решить, какое значение дать $ new_name. Конечно, это может быть полный путь к библиотеке, и таким образом библиотеки Boost будут вести себя как другие ваши зависимости.
Альтернатива — более легко поддающаяся распространению — использует RPATH. (Имена установки на основе RPath ложатся бременем на зависимость, чтобы найти ее зависимость: в зависимости хранится список путей, которыми он будет пытаться заменить «@rpath»):
install_name_tool libboost_regex.dylib -id @rpath/libboost_regex.dylib #assign a rpath dependant install name to a boost library
install_name_tool myLib -add_rpath $a_rpath_prefix # adds a candidate to substitute @rpath with, stored in myLib
$a_rpath_prefix
может быть путем к папке, содержащей ваши библиотеки Boost, которая будет хорошо работать в вашей среде разработки. И если однажды вам понадобится распространить вашу библиотеку, вы можете встроить зависимости Boost в относительный путь (или в пакет OS X) и добавить значение RPath, которое будет следовать этому относительному пути.
Для конкретного случая, когда вы описываете автоматическую проверку, которая не может обнаружить Boost, вы можете решить ее с помощью альтернативного решения, предложенного выше. Это изменяет имя установки библиотеки Boost, которая хранится в самой библиотеке (и, таким образом, будет скопирована в libA.dylib
):
install_name_tool libboost_regex.dylib -id /full/path/to/libboost_regex.dylib
В этом конкретном случае использования еще более простым решением может быть заполнение DYLD_FALLBACK_LIBRARY_PATH
с путем к каталогу, содержащему вашу библиотеку Boost. Динамический компоновщик будет искать в этих каталогах библиотеки, поэтому он найдет там библиотеки повышения. В терминале, в котором будет выполняться проверка сборки:
export DYLD_FALLBACK_LIBRARY_PATH=/full/path/to/;$DYLD_FALLBACK_LIBRARY_PATH
Других решений пока нет …