Как применить опцию -fvisibility к символам в статических библиотеках?
У меня есть проект общей библиотеки, который построен из 4 статических библиотек (.a
) и одного объекта (.o
). Я пытаюсь добавить параметр -fvisibility=hidden
для ограничения символов на выходе только теми, которые я отмечаю в источнике с помощью __ атрибута __.
Я добавил параметр -fvisibility=hidden
в параметры компиляции для проекта .so
(который охватывает файл .o
) и для проектов .a
.
Символы в объектном файле удаляются, как ожидалось, из окончательного .so
. Однако символы из проектов .a
все еще находятся в финальном файле .so
. Добавление опции -fvisibility=hidden
в ссылку .so
не имеет эффекта.
Что я делаю неправильно?
Моя цель - удалить из .so
все символы, кроме функций интерфейса, в библиотеку.
EDIT: я фактически использовал карту для решения этой проблемы на данный момент. Однако это требует продолжения обслуживания версии script по мере изменения внешних символов. Принятый ответ имеет лучшую идею.
Ответы
Ответ 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 после определения, какой компоновщик имеет система.