Как разрешить компиляцию статического двоичного файла, в код которого включена функция gethostbyname и если она скомпилирована без предупреждения, например:
предупреждение: использование gethostbyname в статически связанных приложениях
требует во время выполнения общих библиотек из используемой версии glibc
для связи
Я собираю на Ubuntu 12.04 с командой:
$ gcc -static lookup.c -o lookup
Это код для lookup.c:
/* lookup.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
extern int h_errno;
int main(int argc,char **argv) {
int x, x2;
struct hostent *hp;
for ( x=1; x<argc; ++x ) {
hp = gethostbyname(argv[x]);
if ( !hp ) {
fprintf(stderr,
"%s: host '%s'\n",
hstrerror(h_errno),
argv[x]);
continue;
}
printf("Host %s : \n" ,argv[x]);
printf(" Officially:\t%s\n", hp->h_name);
fputs(" Aliases:\t",stdout);
for ( x2=0; hp->h_aliases[x2]; ++x2 ) {
if ( x2 ) {
fputs(", ",stdout);
}
fputs(hp->h_aliases[x2],stdout);
}
fputc('\n',stdout);
printf(" Type:\t\t%s\n",
hp->h_addrtype == AF_INET
? "AF_INET" : "AF_INET6");
if ( hp->h_addrtype == AF_INET ) {
for ( x2=0; hp->h_addr_list[x2]; ++x2 ) {
printf(" Address:\t%s\n",
inet_ntoa( *(struct in_addr *)
hp->h_addr_list[x2]));
}
}
putchar('\n');
}
return 0;
}
Я хочу, если я проверю через $ file lookup
получит вывод так:
поиск: ELF 32-битный исполняемый файл LSB, Intel 80386, версия 1 (GNU / Linux),
статически связанный, для GNU / Linux 2.6.24,
BuildID [sha1] = 0x6fcb2684ad8e5e842036936abb50911cdde47c73, без зачистки
Не так:
поиск: ELF 32-битный исполняемый файл LSB, Intel 80386, версия 1 (SYSV),
динамически связанные (использует разделяемые библиотеки), для GNU / Linux 2.6.24,
BuildID [sha1] = 0xf9f18671751927bea80de676d207664abfdcf5dc, не удален
Если вы прокомментировали предложение, я должен использовать без статического, потому что разные libc для каждого Linux я знал, я надеюсь, что вам не нужно комментировать.
Почему я сохраняю статичность?
Поскольку там мне нужно сделать для обязательного использования статических, двоичные файлы должны быть статическими, а не динамическими.
Я более 2 недель искал это, но пока не удалось.
Спасибо за помощь, чтобы решить мою тяжелую проблему.
То, что вы просите, будет очень сложно.
Увидеть этот вопрос StackOverflow о getaddrinfo. В основном под getaddrinfo
/gethostbyname
является уровнем NSS в glibc Это позволяет системному администратору сказать «использовать DNS для преобразования имен хостов в IP-адреса», или «использовать LDAP», или «не использовать ничего, кроме /etc/hosts
Msgstr «Этот элемент управления во время выполнения; системный администратор может в любой момент изменить способ разрешения имен хостов по IP-адресам.
Из-за этой гибкости все вызовы разрешения имен в glibc используют вспомогательные библиотеки (в основном плагины), чтобы выполнять основную работу по разрешению. Существует одна общая библиотека для адресации LDAP, одна для файлов, одна для DNS, одна для YP и так далее и так далее.
Если вы хотите, чтобы ваша программа была на 100% статически связана, вам придется пойти в другое место (НЕ gethostbyname
) для преобразования имени хоста в IP-адрес. Вы можете сделать это с помощью библиотеки резолвера, такой как uDNS (не совсем такой — есть похожие инструменты), но вы должны помнить, что ваш бинарный файл не собирается делать правильные вещи в системах, которые настроены не использовать DNS!
Вместо этого я бы рекомендовал просто оставить программу (технически) динамически связанной. Если вы действительно хотите убедиться, что он будет работать на любой платформе, вы можете даже отправить glibc
с бинарным — хотя для этого потребуется соответствие LGPL. Если оставить эту единственную динамическую ссылку на месте, это будет означать, что вы не будете работать в системах с неправильной glibc
версия — не большая проблема совместимости.
Говоря о соответствии лицензии, стоит отметить, что если вы статически связываете glibc
вам, скорее всего, придется отправить исходный код для вашего все приложение соблюдать glibc
лицензия LGPL. Я не юрист, и это не квалифицированная юридическая консультация, но чтение LGPL очень ясно показывает, что приложения статически связаны glibc
должен быть с открытым исходным кодом. Увидеть этот вопрос StackOverflow по теме.
Я получаю то же предупреждение, и чтобы исправить это, я перекомпилировал glibc. Включить выключатель --enable-static-nss
при настройке, чтобы заставить его работать.
У меня есть 2 ответа —
Держите основную часть вашей программы статически связанной, и выделите одну функциональную программу, чтобы просто вызвать gethostbyname (). Позвольте последнему быть динамически связанным. Используя fork, затем exec выполняет эту отдельную программу, чтобы получить адрес для доменного имени. Вместо fork и exec вы можете использовать system (), хотя это занимает больше времени (целую миллисекунду), что не должно вызывать беспокойства, так как вы все равно ищете серверы имен в Интернете, что занимает время.
Напишите исходный код, чтобы сделать DNS, как я сделал. Скомпилируйте его в архив (.a) и выполните поиск в статических ссылках.