Как создать статическую библиотеку для iOS, не делая все символы общедоступными

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

Мотивация: Создание статической библиотеки для использования другими разработчиками iOS. Некоторые символы в библиотеке вызовут проблемы при экспорте, поэтому я хочу сделать их внутренними символами. С динамической библиотекой это просто, просто используйте аргумент -exported_symbols_list libtool (ld) и перечислите те, которые вы хотите публиковать. libtool документация не позволит этот аргумент для статических библиотек.

В библиотеке есть несколько файлов ObjectiveC.m, которые используют код друг от друга. Только один класс в группе должен быть доведен до сведения конечного файла статической библиотеки .a.

Пробовал libtool -exported_symbols_list publicsymbols.exp, но этот аргумент libtool не поддерживается -static для статических библиотек.

Невозможно сделать символы приватными с атрибутами (если это даже работает), потому что они необходимы другим .m файлам в группе.

выглядит так: ld может принимать несколько файлов .o и связывать их вместе в новый .o файл (через аргумент -r), и он не имеет "динамического единственного" отказа от ответственности для аргумента -exported_symbols_list (что может быть просто нечеткой документацией...).

как тест Я строю свой проект с Xcode, поэтому у меня есть все файлы .o, а затем попробуйте вызвать ld в командной строке, например:

ld -r -x -all_load -static -arch armv6 -syslibroot {path} 
   -filelist /Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCsdk.LinkFileList 
   -exported_symbols_list {exp file path} -o outputfile.o

где объекты типа {path} имеют длинные пути к соответствующим местам там.

но я получаю следующие ошибки:

/usr/bin/ld_classic:/Users/Dad/ABCsdk/iphone-ABClib/build/ABCLib.build/Distribution-iphoneos/ABCLib-device.build/Objects-normal/armv6/ABCmain.o несовместимый, файл содержит неподдерживаемый тип раздела 3 (_TEXT, _picsymbolstub4) в команде нагрузки 0 (необходимо указать "-динамический", который будет использоваться)

поэтому что-то кажется неправильным...

Кто-нибудь знает умный способ сделать эту работу? Спасибо.

Ответ 1

Это действительно невозможно, мне жаль говорить. Это связано с тем, как работают статические библиотеки. Статическая библиотека - это нечто большее, чем совокупность объединенных файлов *.o, но динамическая библиотека - загружаемое двоичное изображение, как и исполняемый файл.

Предположим, у вас есть четыре файла,

  • common.c определяет common, который "private"
  • fn1.c определяет fn1, который вызывает common.
  • fn2.c определяет fn2, который вызывает common.
  • other.c определяет other.

В динамической библиотеке компоновщик объединяет все в один большой кусок кода. Библиотека экспортирует other, fn1 и fn2. Вам нужно загрузить всю библиотеку или ничего из нее, но две программы могут загружать ее, не помещая несколько копий в память. Точка входа в common просто отсутствует в таблице символов - вы не можете вызывать ее из-за пределов библиотеки, потому что компоновщик не может ее найти.

Обратите внимание, что приложение и общая библиотека имеют, по существу, один и тот же формат: приложение в основном является общей библиотекой, которая экспортирует только один символ, main. (Это не совсем так, но близко.)

В статической библиотеке компоновщик никогда не запускается. Все файлы скомпилируются в файлы *.o и помещаются в архив библиотеки *.a. Внутренние ссылки не будут решены.

Предположим, что ваше приложение вызывает fn1. Компилятор видит неразрешенный вызов fn1, а затем просматривает библиотеки. Он находит определение для fn1 в fn1.o. Затем компоновщик замечает неразрешенный вызов common, поэтому он выглядит обычным. Эта программа не получит код из fn2.c или other.c, потому что он не использует определения из этих файлов.

Статические библиотеки очень старые, и у них нет функций динамических библиотек. Вы можете представить себе статическую библиотеку, как в основном zip файл, полный скомпилированного исходного кода, в отличие от динамической библиотеки, которая связана между собой. Никто никогда не удосужился расширить формат архива, чтобы добавить видимость символов. Когда вы связываетесь со статической библиотекой, вы получаете такой же результат, как если бы вы добавили исходный код библиотеки в свою программу.

Краткая версия: Динамическая библиотека имеет одну таблицу символов всех экспортированных символов, но ни один из частных символов. Точно так же объектный файл имеет список всех его символов extern, но ни один из static. Но статическая библиотека не имеет таблицы символов, это просто архив. Таким образом, нет механизма, чтобы сделать код закрытым для статической библиотеки (кроме определения объектов static, но это не работает для классов Objective-C).

Если бы мы знали, почему вы пытались это сделать, возможно, мы могли бы дать вам предложение. (Является ли это для безопасности? Имя столкновения? Все эти вопросы имеют решения.)

Ответ 2

XCode BuildSetting может это сделать! 1. Установите Perform Single-Object Prelink в YES 2. Установите Exported Symbols File в path_for_symbols_file

возможно, вы должны удалить -static, -exported_symbols_list не может работать с static lib, но может вступить в силу для объектного файла.