Вопрос

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

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

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

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

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


Кажется, мне не нужно использовать otool для сброса пути поиска.Если я отредактирую «Информацию о цели» -> «Сборка» -> «Развертывание» -> «Каталог установки», я могу изменить изнутри XCode путь, который dyld будет искать в поисках dylib.По умолчанию для нового проекта динамической библиотеки путь был установлен как /usr/local/lib.который я изменил на ./ - otool подтверждает, что ./ теперь находится там, где dyld будет искать этот конкретный динамический модуль.К сожалению, ./, похоже, на самом деле не относится ни к одному каталогу в моем пакете приложений :(

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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

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

Удачи.

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

У Dylibs есть имя установки, которое указывает, где вы их установили, когда делали это в первый раз (macports устанавливает их в /opt/local/lib/).У них также есть путь к другим библиотекам dylib, которые им нужны для работы.Например, если у вас есть dylib под названием «libopencv_core.2.4.8.dylib», вы можете проверить имя установки и пути к другим 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- Вторая линия:Установите имя dylib, который вы проверяете.(macports устанавливает их в /opt/local/lib/)

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

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

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

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

@executable_path/../Frameworks/nameOFTheDylib.dylib

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

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

В итоге сделал это так:

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

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.Вы можете проверить это в некоторых dylibs с помощью команды:

otool -L theDylibYouPrefer.dylib

б) Выберите только необходимые библиотеки, а не всю папку lib:

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

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 dylib)

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

И всё, у меня это получилось более-менее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top