Подтвердить что ты не робот

Связывание статических библиотек с другими статическими библиотеками

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

Моя статическая библиотека, позволяет называть ее X, компилируется отлично.

Я создал простую примерную программу, которая использует функцию из X, но когда я пытаюсь связать ее с X, я получаю много ошибок о недостающих символах из библиотек a_1 - a_n.

Есть ли способ создать новую статическую библиотеку Y, содержащую X и всю функциональность, необходимую X (выбранные биты из a_1 - a_n), чтобы я мог распространять только Y, чтобы люди могли связать свои программы с


UPDATE:

Я посмотрел только на сброс всего с ar и создание одной мега-библиотеки, однако, которая заканчивается, включая множество символов, которые не нужны (все файлы .o около 700 MB, однако, статически связанный исполняемый файл - 7 МБ). Есть ли хороший способ включить только то, что на самом деле необходимо?


Это тесно связано с Как объединить несколько библиотек C/С++ в один?.

4b9b3361

Ответ 1

Статические библиотеки не связаны с другими статическими библиотеками. Единственный способ сделать это - использовать ваш инструмент библиотекаря/архиватора (например, ar в Linux), чтобы создать одну новую статическую библиотеку, объединив несколько библиотек.

Изменить: В ответ на ваше обновление, единственный способ, которым я знаю, выбирать только требуемые символы - это вручную создать библиотеку из подмножества файлов .o, которые их содержат. Это сложно, требует много времени и ошибок. Я не знаю никаких инструментов, которые помогут сделать это (не сказать, что их не существует), но это создаст интересный проект для его создания.

Ответ 2

Если вы используете Visual Studio, тогда да, вы можете это сделать.

Инструмент построения библиотеки, поставляемый с Visual Studio, позволяет вам объединять библиотеки в командной строке. Однако я не знаю, как это сделать в визуальном редакторе.

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib

Ответ 3

В Linux или MingW с помощью GNU toolchain:

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

Если вы не удаляете liba.a и libb.a, вы можете создать "тонкий архив":

ar crsT libab.a liba.a libb.a

В Windows с программной цепочкой MSVC:

lib.exe /OUT:libab.lib liba.lib libb.lib

Ответ 4

Статическая библиотека - это просто архив объектных файлов .o. Извлеките их с помощью ar (предположим Unix) и упакуйте их обратно в одну большую библиотеку.

Ответ 5

В качестве альтернативы Link Library Dependencies в свойствах проекта существует еще один способ связать библиотеки в Visual Studio.

  • Откройте проект библиотеки (X), который вы хотите объединить с другими библиотеками.
  • Добавьте другие библиотеки, которые вы хотите объединить с X (правый клик, Add Existing Item...).
  • Перейдите к их свойствам и убедитесь, что Item Type есть Library

Это будет включать другие библиотеки в X, как если бы вы запускали

lib /out:X.lib X.lib other1.lib other2.lib

Ответ 6

Обратите внимание, прежде чем вы прочтете остальное: Оболочка script, показанная здесь, безусловно, небезопасна для использования и хорошо протестирована. Используйте на свой страх и риск!

Я написал bash script для выполнения этой задачи. Предположим, что ваша библиотека - lib1, и вам нужно добавить некоторые символы из lib2. script теперь выполняется в цикле, где он сначала проверяет, какие символы undefined из lib1 могут быть найдены в lib2. Затем он извлекает соответствующие объектные файлы из lib2 с помощью ar, немного переименовывает их и помещает в lib1. Теперь может быть больше недостающих символов, потому что материал, который вы включили из lib2, нуждается в другом материале из lib2, который мы еще не включили, поэтому цикл должен запускаться снова. Если после некоторых проходов цикла больше никаких изменений, т.е. Никаких объектных файлов из lib2, добавленных в lib1, цикл может остановиться.

Обратите внимание, что включенные символы по-прежнему отображаются как undefined на nm, поэтому я отслеживаю файлы объектов, которые были добавлены в lib1, сами, чтобы определить, может ли цикл быть остановлен.

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

Я назвал это script libcomp, поэтому вы можете вызвать его, например, с

./libcomp libmylib.a libwhatever.a

где lib, независимо от того, где вы хотите включить символы. Тем не менее, я считаю, что лучше всего скопировать все в отдельный каталог. Я бы не стал доверять моему script так много (однако, это сработало для меня, я мог бы включить libgsl.a в мою библиотеку с этим и оставить этот -lgsl-компилятор).