LINUX.ORG.RU

Что не так с линковкой libzip?

 , ,


0

3

Решил использовать libzip для работы с zip-файлами. Установлена libzip и libzip-dev (в Debian)

Однако невозможно собрать программу. Ругается, что не может найти функции из libzip

#include <stdio.h>
#include <stdlib.h>
#include <zip.h>

int main(int argc, char **argv) {
  struct zip *zip_file;
  int err;
  
  zip_file = zip_open(argv[1], 0, &err);
	if (!zip_file) {
		fprintf(stderr,"Error: can't open file %s\n",argv[1]);
		return -1;
	};
  return 0;
}

Компилирую так

 gcc -lzip testzip.c -o testzip
/usr/bin/ld: /tmp/ccNAFwSq.o: in function `main':
testzip.c:(.text+0x27): undefined reference to `zip_open'
collect2: error: ld returned 1 exit status

WTF? Все как в манах сделано:

NAME
     zip_open, zip_open_from_source — open zip archive

LIBRARY
     libzip (-lzip)

SYNOPSIS
     #include <zip.h>

     zip_t *
     zip_open(const char *path, int flags, int *errorp);

     zip_t *
     zip_open_from_source(zip_source_t *zs, int flags, zip_error_t *ze);

Попытка прямо указать библиотеку тоже ничего не дает

$ gcc /usr/lib/x86_64-linux-gnu/libzip.so testzip.c -o testzip
/usr/bin/ld: /tmp/cc34lYsN.o: in function `main':
testzip.c:(.text+0x27): undefined reference to `zip_open'
collect2: error: ld returned 1 exit status
gcc -lzip -L /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/libzip.so testzip.c -o testzip
/usr/bin/ld: /tmp/ccyCCaCm.o: in function `main':
testzip.c:(.text+0x27): undefined reference to `zip_open'
collect2: error: ld returned 1 exit status

В библиотеке нужные функции есть

$ strings /usr/lib/x86_64-linux-gnu/libzip.so|grep zip_open
zip_open_from_source
zip_open

Такое ощущение, что или поломано что-то или забыта какая-то магическая опция -DМАГИЧЕСКАЯ_ОПЦИЯ_О_КОТОРОЙ_НЕ_СКАЗАЛИ_В_ДОКУМЕНТАЦИИ

P.S. замена struct zip *zip_file на zip_t *zip_file ничего не дает, да и не могла дать.

★★★★★

Последнее исправление: praseodim (всего исправлений: 1)

Ответ на: комментарий от i-rinat

Получилось. Чувствую себя идиотом, но в чем фокус? Если меня не переклинило, то вроде я раньше в аналогичных случаях -l ставил вначале и ничего было.

P.S. Видимо таки переклинило, потому что сейчас поискал и прочел, что содержимое библиотек до имени файла линковщик игнорирует. Хм.

praseodim ★★★★★
() автор топика
Последнее исправление: praseodim (всего исправлений: 2)
Ответ на: комментарий от praseodim

Не помню точно год, но где-то в районе 2015-го компоновщик перешёл на использование --as-needed по умолчанию. Раньше компоновщик сваливал все объекты и библиотеки в большое месиво и сращивал нужное. А после изменения стал обрабатывать элементы линковки по одному, слева направо. Теперь если библиотека не содержит ни одного символа, который удовлетворяет неразрешённую на текущий момент зависимость, она просто отбрасывается. Так что теперь важен порядок линковки. Сначала объектники от основной программы, потом их зависимости, потом зависимости зависимостей.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Ага. Нет, такие вещи ночью не надо пытаться понять. Я было подумал уже, что ошибочно помню, что у меня работала опция -l вначале.

В общем, да, поискал как вернуть старое поведение. Новое поведение может быть отключено опцией --no-as-needed

$gcc -Wl,--no-as-needed -lzip testzip.c -o testzip

Нормально компилирует.

praseodim ★★★★★
() автор топика
Последнее исправление: praseodim (всего исправлений: 1)