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

StackOverflow https://stackoverflow.com/questions/2157629

  •  23-09-2019
  •  | 
  •  

Вопрос

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

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

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

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


Обновить:

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


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

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

Решение

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

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

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

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

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

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

На 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

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

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

  1. Откройте проект библиотеки (X), которую вы хотите объединить с другими библиотеками.
  2. Добавьте другие библиотеки, которые вы хотите объединить с X (щелкните правой кнопкой мыши, Add Existing Item...).
  3. Зайдите в их свойства и убедитесь Item Type является Library

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

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

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

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

Обратите внимание, что включенные символы по-прежнему сообщаются как неопределенные с помощью 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

Я назвал этот сценарий libcomp, так что вы можете вызвать это тогда , напримерс

./libcomp libmylib.a libwhatever.a

где libwhatever - это то место, откуда вы хотите включить символы.Однако я думаю, что безопаснее всего сначала скопировать все в отдельный каталог.Я бы не стал так сильно доверять своему сценарию (однако у меня он сработал;Я мог бы включить libgsl.a в свою библиотеку numerics с этим и исключить этот переключатель компилятора -lgsl).

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