При связывании есть ли что-то между захватом того, что вам нужно, и захватом всего (-Wl, --целого-архива)?

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

В качестве альтернативы я могу заставить компоновщик подобрать все в статической библиотеке, если я укажу параметр -Wl,--whole-archive для GCC, т.е. укажу параметр --whole-archive для ссылки GNU.

Но есть ли золотая середина? Можно ли пометить некоторые символы и сделать так, чтобы компоновщик всегда подбирал их для исполняемого файла, а остальные символы добавлялись только при необходимости?

Мотивация: я использую несколько статических блоков для регистрации классов на фабрике; Я хочу сделать свой код доступным в виде (нединамической) библиотеки, чтобы пользовательский код не выполнял никаких «магических заклинаний» для заполнения фабрики.

Некоторые связанные вопросы:


person einpoklum    schedule 18.04.2017    source источник
comment
Вы когда-нибудь находили альтернативу --whole-archive?   -  person tmm1    schedule 11.08.2019
comment
@ tmm1: Нет, я как бы разочаровался в этом.   -  person einpoklum    schedule 11.08.2019
comment
Я думаю, что --undefined - единственное другое решение. Подробнее см. stackoverflow.com/a/47186765/332798.   -  person tmm1    schedule 11.08.2019


Ответы (1)


Вы можете заставить компоновщик сохранить заданную функцию (и, естественно, весь код, который вызывается из этой функции). Добавьте -u my_function к команде ссылки. Многие системы сборки позволяют статическим библиотекам «экспортировать» настройки сборки тем, кто их использует. Например, для платформы Android ndk-build вы можете указать что-то вроде

include $(CLEAR_VARS)
LOCAL_MODULE := the_best_static_library
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_LDFLAGS := -u my_function
include $(PREBUILT_STATIC_LIBRARY)

в вашем модуле Android.mk. Люди повторно используют его, добавляя в свой Android.mk простой оператор

$(call import-module,third_party/the_best_static_library)

Примечание. Чтобы этот подход работал, my_function() нельзя объявлять static. Если какой-то символ объявлен как статический в области файла, то компоновщик предполагает, что он вообще не знает его по имени. К счастью, если на него есть ссылка в каком-то коде, который компоновщик решит сохранить, он также не будет удален. Кроме того, если вы не предпримете особых усилий, компоновщик удалит или сохранит целые единицы компиляции (также известные как C-файлы). Таким образом, обычно достаточно "привязать" фиктивную функцию к сохранить множество функций и данных.

person Alex Cohn    schedule 10.05.2017
comment
(1) Какая часть этого примера относится к Android? Уважает ли GNU все эти флаги? (2) о static - вы имеете в виду не объявлять его статическим в области файла, верно? На самом деле это было бы проблематично для меня ... но тем не менее, +1 сейчас, и когда у меня будет возможность попробовать, я соглашусь. - person einpoklum; 10.05.2017
comment
Я расширил ответ о statuc. Что касается флага компоновщика, насколько я знаю, он доступен в любой цепочке инструментов на основе gcc. Специфические для Android вещи — это то, как вы распространяете знания среди пользователей вашей статической библиотеки. Как вы помогаете им получить доступ к вашим заголовочным файлам? Как вы объясните им, что ваш код зависит от некоторых сторонних готовых библиотек? - person Alex Cohn; 10.05.2017