динамические библиотеки в XCode - PullRequest
5 голосов
/ 02 декабря 2009

Я пытаюсь создать приложение Mac в XCode, которое частично реализовано в динамической библиотеке.

Я добавил новую цель (динамическую библиотеку) в свой проект какао XCode и после небольшого сражения с фреймворками и предварительно скомпилированными заголовками, скомпилировал dynlib - и успешно запустился из отладчика.

При автономной работе очевидно, что dynlib находится не в том месте. Msgstr "Библиотека не загружена: /usr/local/lib/testlib.dynlib". В Windows - моей более обычной платформе - Dll можно поместить в ту же папку, что и exe, и в любом месте системного пути.

Я бы предпочел, чтобы мое приложение искало его dynlib где-то в его комплекте приложений (и некоторые документы, кажется, подтверждают это как правильный подход), но я не знаю как.

Можно ли настроить проект в XCode таким образом, чтобы файл dylib фактически копировался в комплект приложения в месте, где приложение его будет искать?


Кажется, мне не нужно использовать otool для сброса пути поиска. Если я отредактирую Target Info -> Build -> Deployment -> Installation Directory, я могу изменить изнутри XCode путь, который dyld будет искать для dylib. По умолчанию для нового проекта динамической библиотеки путь был установлен на /usr/local/lib. Который я изменил на ./ - otool подтверждает, что ./ сейчас там, где dyld будет искать этот конкретный динамический модуль. К сожалению ./, похоже, на самом деле не ссылается ни на один каталог в моем комплекте приложений: (* ​​1014 *

Итак, мои вопросы (не отвеченные в другой ветке) теперь таковы: 1. Как ввести осмысленный относительный путь в настройках Target Info -> ... -> Installation Directory, и 2. Как я могу заставить XCode автоматически скопировать «цель» dylib в папку пакета цели целевого приложения в соответствующем месте?

Ответы [ 3 ]

6 голосов
/ 02 декабря 2009

Наконец. Нашел официальную документацию . Это возможно сделать полностью в XCode.

Я был на полпути, изменяя настройку установленного каталога библиотеки: Это должно было быть: @executable_path/../Frameworks

Затем мне нужно было добавить шаг сборки «Копировать файлы» в библиотеку, чтобы фактически скопировать его в папку Frameworks.

Simple. Автоматический.

1 голос
/ 02 декабря 2009

Я полагаю, что вы не копируете динамическую библиотеку в комплект приложений во время компиляции.

Приложение ищет точку в файловой системе, но делает это только после того, как не находит ее внутри пакета приложения. Вам нужно использовать команду otool, чтобы изменить двоичный файл после его компиляции (используя скрипт сборки).

Вы найдете ответ на этот ранее заданный вопрос: Как мне создать динамическую библиотеку в Xcode .

Удачи.

0 голосов
/ 26 февраля 2014

После долгих исследований, которые я получил, я пытался упаковать некоторые dylib openCV с моим приложением, потому что я получал ошибку "Библиотека не загружена: ....".

У Dylibs есть имя установки, которое указывает, куда вы установили их, когда вы делали это в первый раз (macports устанавливает их в / opt / local / lib /). У них также есть путь к другим дилибам, которые им нужны для работы. Например, если у вас есть библиотека dylib с именем «libopencv_core.2.4.8.dylib», вы можете проверить имя установки и пути к другим библиотекам, которые он использует, с помощью этой команды:

otool -L libopencv_core.2.4.8.dylib

Вывод команды:

libopencv_core.2.4.8.dylib:
/opt/local/lib/libopencv_core.2.4.dylib (compatibility version 2.4.0, current version 2.4.8)
/opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

1- Первая строка: имя проверяемого файла.

2- Вторая строка: установите имя проверяемого дилиба. (macports устанавливает их в / opt / local / lib /)

3- Третья строка: путь к другим дискам, которые нужны для работы, которые есть не во всех системах OSX. (macports устанавливает их в / opt / local / lib /, и они у вас есть, потому что вы ранее установили, поэтому, если вы распространяете свое приложение на другие macs, вы получаете ошибку «библиотека не найдена»)

4 & 5 - Строки 4 и 5: dylibs внутри всех систем macOSX. вам не нужно копировать их в свой проект.

Теперь мы знаем это, наши цели:

1- Измените все пути внутри dylibs (установите имена и пути к другим необходимым dylib), потому что мы собираемся поместить наши dylibs в приложение в каталог «Frameworks», а когда мы перемещаем приложение или копируем его другим mac мы хотим, чтобы dylib искали друг друга в папке «frameworks» внутри каталога нашего приложения: путь, который мы будем использовать:

@executable_path/../Frameworks/nameOFTheDylib.dylib

(ПРИМЕЧАНИЕ, ДВЕ ТОЧКИ ДЕЙСТВИТЕЛЬНО ВАЖНЫ!)

2- Скопируйте в xCode все необходимые нам дилибы, но не все, находящиеся в папке / opt / local / lib, ТОЛЬКО ТО, ЧТО МНЕ НУЖНО: (все они слишком большие, может быть, 500 МБ), которые нам понадобятся чтобы перейти по ссылкам от известных нам дилибов (обычно 4 или 5) и включенных дилибов, потому что эти 4 или 5 нуждаются в них для работы.

Y наконец-то сделал это так:

а) Чтобы изменить пути:

1- Скопируйте все файлы / opt / local / lib на рабочий стол.

2 - Удалите все файлы в папке lib, которые НЕ являются архивами .dylib.

3-Поместите этот скрипт в папку lib (вместе с dylibs), которую мы только что скопировали на рабочий стол:

(Скопируйте этот текст в textEdit и сохраните его как NameYouPrefer.sh)

#!/bin/bash
echo empieza el script

EXECFILE=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}
OLDLIBPATH="/opt/local/lib/"
NEWLIBPATH="@executable_path/../Frameworks/"
ACTUALPATH=`pwd`
# space separated list of libraries
for TARGET in ${ACTUALPATH}/* ; do
TARGET=$(basename $TARGET)
    if [ ${TARGET: -6} == ".dylib" ]
    then
        echo otool -DX ${TARGET}
        TARGETID=`otool -DX ${TARGET}`
        echo ${TARGETID}

        echo install_name_tool -id ${NEWLIBPATH}${TARGET} ${TARGET}
        echo `install_name_tool -id ${NEWLIBPATH}${TARGET} ${TARGET}`

        for DYLIB in ${ACTUALPATH}/* ; do
        DYLIB=$(basename $DYLIB)
            if [ ${DYLIB: -6} == ".dylib" ]
            then
                echo install_name_tool -change ${TARGETID} ${NEWLIBPATH}${TARGET} ${DYLIB}
                echo `install_name_tool -change ${TARGETID} ${NEWLIBPATH}${TARGET} ${DYLIB}`
            else
                if [ ${DYLIB: -3} == ".sh" ]
                then
                    echo soyYo
                else
                    echo mkdir ${ACTUALPATH}/eliminadas/
                    echo `mkdir ${ACTUALPATH}/eliminadas/`
                    echo mv ${DYLIB} ${ACTUALPATH}/eliminadas
                    echo `mv ${TARGET} ${ACTUALPATH}/eliminadas`
                fi
            fi
        done
    else
if [ ${TARGET: -3} == ".sh" ] || ![ -h ${TARGET} ]
        then
            echo noMeElimino
        else
            echo mkdir ${ACTUALPATH}/eliminadas/
            echo `mkdir ${ACTUALPATH}/../eliminadas/`
            echo mv ${TARGET} ${ACTUALPATH}/eliminadas/${TARGET}
            echo `mv ${TARGET} ${ACTUALPATH}/../eliminadas`
        fi
    fi
done

echo finaliza el script

4- Выполнить это:

cd Desktop/lib
sudo ./theNameYouPrefer.sh

ДЕЙСТВИТЕЛЬНО ВАЖНО запускать его как sudo, потому что dylibs могут быть защищены от записи.

В этот момент вы должны изменить все пути dylibs. Вы можете проверить это в некоторых библиотеках с помощью команды:

otool -L theDylibYouPrefer.dylib

b) Выберите только нужные dylibs, а не все папки lib:

1-Переименуйте папку lib в lib2: lib =====> lib2

2 - Создайте на рабочем столе еще одну папку (с именем, которое вы предпочитаете, например, exampleFolder), СЛЕДУЮЩАЯ К папке lib2.

3- Скопируйте в exampleFolder важные дилибы, которые, как вы знаете, вам наверняка понадобятся, в моем случае это: libopencv_core.2.4.8.dylib, libopencv_highgui.2.4.8.dylib, libopencv_imgproc.2.4.8.dylib , libopencv_objdetect.2.4.8.dylib

4- Скрипт: скопируйте его в exampleFolder, рядом с важными библиотеками. Я не очень разбираюсь в скриптах, поэтому этот немного более грязный:

#!/bin/bash
echo empieza el script

EXECFILE=${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}
OLDLIBPATH="/opt/local/lib/"
NEWLIBPATH="@executable_path/../Frameworks/"
ACTUALPATH=`pwd`
# space separated list of libraries
for TARGET in ${ACTUALPATH}/* ; do
TARGET=$(basename $TARGET)
    if [ ${TARGET: -6} == ".dylib" ]
    then
        echo otool -DX ${TARGET}
        TARGETID=`otool -L ${TARGET}`
echo ${TARGETID}

echo :::::::::::::::::::::::::::

ELIM=`echo ${TARGETID} | sed 's/([^)]*)/UUU/g'`
echo $ELIM
#echo ${TARGETID} | sed 's/([^)]*)/UUU/g'
ELIM=`echo $(awk '{gsub("@executable_path/../Frameworks/", "");print}' <<< ${ELIM})`
echo $ELIM

ELIM=`echo $(awk '{gsub(" UUU", "");print}' <<< ${ELIM})`
echo $ELIM

ELIM=`echo $(awk '{gsub(":", "");print}' <<< ${ELIM})`
echo $ELIM

IFS=' ' read -a ARRAY <<< $ELIM

for element in ${ARRAY[@]}
do
    echo $element
    if [[ ${element} == */* ]]
    then
        echo "NO FRAMEWORK";
    else
        echo `mkdir ${ACTUALPATH}/../copy`
        echo `cp ${ACTUALPATH}/../lib2/${element} ${ACTUALPATH}/${element}`
    fi
done


    else
if [ ${TARGET: -3} == ".sh" ] || ![ -h ${TARGET} ]
        then
            echo noMeElimino
        else
            echo mkdir ${ACTUALPATH}/eliminadas/
            echo `mkdir ${ACTUALPATH}/../eliminadas/`
            echo mv ${TARGET} ${ACTUALPATH}/eliminadas/${TARGET}
            echo `mv ${TARGET} ${ACTUALPATH}/../eliminadas`
        fi
    fi
done

echo finaliza el script

5- Выполнять этот скрипт много раз, пока вы не поймете, что количество файлов внутри exampleFolder не меняется.

6- Все нужные вам дилибы находятся внутри exampleFolder! В моем случае я получил 61 дилиб. (помните, когда мы начинали, я поместил туда 4 дилиба)

7- Последнее, что вам нужно сделать, это поместить папку «Frameworks» в xCode. После этого ПОМНИТЕ, ЧТОБЫ ПОЙТИ, ЧТОБЫ «СОЗДАТЬ ФАЗЫ» И ДОБАВИТЬ А »скопировать файлы» ФАЗА: «редактор» => «добавить фазу сборки» => «Добавить фазу сборки файлов копирования» И ВНУТРИ «ФАЙЛОВ КОПИРОВАНИЯ» ФАЗА НАЖМИТЕ НА ПЛЮС ЗНАЧИТЕ И ДОБАВЬТЕ ВСЕ ДИЛИБЫ, КОТОРЫЕ ВЫ НАЙДЕТЕ В ПАПКУ "Framewroks". Нужное место назначения - Frameworks.

И это все, я понял это более или менее.

...