Почему __attribute __ ((конструктор)) не работает в статической библиотеке?
-
05-07-2019 - |
Вопрос
В следующем примере программа должна напечатать " foo с названием ":
// foo.c
#include <stdio.h>
__attribute__((constructor)) void foo()
{
printf("foo called\n");
}
// main.c
int main()
{
return 0;
}
Если программа скомпилирована следующим образом, она работает:
gcc -o test main.c foo.c
Однако, если foo.c скомпилирован в статическую библиотеку, программа ничего не печатает.
gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o
Почему это происходит?
Решение
Компоновщик не включает код в foo.a в конечную программу, потому что ничто в main.o не ссылается на него. Если main.c
переписать следующим образом, программа будет работать:
//main.c
void foo();
int main()
{
void (*f)() = foo;
return 0;
}
Кроме того, при компиляции со статической библиотекой порядок аргументов для gcc (или компоновщика) имеет большое значение: библиотека должна следовать за объектами, которые на нее ссылаются.
gcc -o test main.o foo.a
Другие советы
Как было указано, символы из архива, на которые нет ссылок, не попадают в выходной двоичный файл, поскольку компоновщик по умолчанию отбрасывает их.
Чтобы переопределить это поведение при связывании со статической библиотекой, для компоновщика можно использовать опции - whole-archive
/ - no-whole-archive
, например:
gcc -c main.c
gcc -c foo.c
ar rcs foo.a foo.o
gcc -o test -Wl,--whole-archive foo.a -Wl,--no-whole-archive main.o
Это может привести к раздутому двоичному файлу, потому что все символы из foo.a
будут включены компоновщиком в вывод, но иногда это оправдано.