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

Как применить опцию -fvisibility к символам в статических библиотеках?

У меня есть проект общей библиотеки, который построен из 4 статических библиотек (.a) и одного объекта (.o). Я пытаюсь добавить параметр -fvisibility=hidden для ограничения символов на выходе только теми, которые я отмечаю в источнике с помощью __ атрибута __.

Я добавил параметр -fvisibility=hidden в параметры компиляции для проекта .so (который охватывает файл .o) и для проектов .a.

Символы в объектном файле удаляются, как ожидалось, из окончательного .so. Однако символы из проектов .a все еще находятся в финальном файле .so. Добавление опции -fvisibility=hidden в ссылку .so не имеет эффекта.

Что я делаю неправильно?

Моя цель - удалить из .so все символы, кроме функций интерфейса, в библиотеку.

EDIT: я фактически использовал карту для решения этой проблемы на данный момент. Однако это требует продолжения обслуживания версии script по мере изменения внешних символов. Принятый ответ имеет лучшую идею.

4b9b3361

Ответ 1

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

Что я хотел бы вам посоветовать, это заменить ваш этап компоновки: gcc -shared -o mylib.so foo.o libbar.a на двухэтапный процесс, в котором вы возвращаете объектные файлы:

  • ar x libbar.a (возможно, в подходящий пустой каталог)
  • gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o

Ответ 2

Просто передайте -Wl,--exclude-libs,ALL в gcc

Это позволит компоновщику преобразовать все скрытые символы в статических библиотеках.

--exclude-libs также принимает список архивов (т.е. имена статических библиотек) для более тонкой детализации, из которых библиотеки скрывают символы.

Примечание: это будет работать только в системах с использованием GNU binutils (например, Linux) или с помощью компоновщика, поддерживающего --exclude-libs (например, он не будет работать с OSX ld64)

Ответ 3

Это ответ на проблему для OS X.

Mac ld не поддерживает --exclude-libs, но поддерживает -exported_symbol sym и применяет его к объектным файлам в статических библиотеках. И когда вы фильтруете в общедоступный API, белый список достаточно мал, чтобы разобрать его.

В конечном итоге я создал в своем Makefile следующее, чтобы сгенерировать -Wl,-exported_symbol,_api_func_1 для каждого экспортируемого символа:

SYMBOLS   = api_func_1 api_func_2 api_func_3 api_func_4
SYMBOLS   += api_func_5 # add more as necessary
COMMA     = ,
LDFLAGS   += $(addprefix -Wl$(COMMA)-exported_symbol$(COMMA)_,$(SYMBOLS))

# ...

libmyapi.so: # ...
    $(CC) -shared -o [email protected] ... $(LDFLAGS)

Затем вы можете if-gate между этой версией флагов и версией GNU ld после определения, какой компоновщик имеет система.