LINUX.ORG.RU

Статическая линковка myapp+libcurl+libssl

 , ,


0

1

Понадобилось статически прилинковать к своему приложению curl+libssl.

Собираю openssl-1.1.1b:

./Configure linux-generic64 no-hw no-engine no-threads no-shared --prefix=/home/user/prg/openssl-1.1.1b_custom --openssldir=/home/user/prg/openssl-1.1.1b_custom

Собираю curl-7.64.1

export PKG_CONFIG_PATH=/home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig
./configure --with-ssl=/home/user/prg/openssl-1.1.1b_custom --disable-shared --without-zlib --disable-pthreads --disable-threaded-resolver --disable-unix-sockets --disable-cookie --without-libssl1.0.2 --without-libssl1.0-dev --without-libssl1.1 --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-sspi --disable-crypto-auth --disable-ntlm-wb --disable-tls-srp --disable-soname-bump --without-libssh2 --disable-curldebug --disable-debug --disable-ipv6 --without-librtmp --disable-ntlm-wb --disable-manual --prefix=/home/user/prg/curl-7.64.1_custom

Пишем тестовое приложение, типа

#include <curl/curl.h>

void test() {

    const char* url = "https://ya.ru";
    CURL* curl;
    CURLcode res;

    curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    res = curl_easy_perform(curl);

    //Если что-то пошло не так...
    if(res != CURLE_OK) {

    curl_easy_strerror(res);
    } else {

    //Все OK
    }

    curl_easy_cleanup(curl);
}

int main(int argc, char** argv) {

    curl_global_init(CURL_GLOBAL_ALL);
    test();
}

и собираем строчкой

cc -Wall --static `pkg-config --static --libs --cflags /home/user/prg/curl-7.64.1_custom/lib/pkgconfig/libcurl.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libcrypto.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libssl.pc` curl-test-1.c -o curl-test-1

Результат:

In function `test':
curl-test-1.c:(.text+0x105): undefined reference to `curl_easy_init'
curl-test-1.c:(.text+0x12a): undefined reference to `curl_easy_setopt'
curl-test-1.c:(.text+0x14c): undefined reference to `curl_easy_setopt'
curl-test-1.c:(.text+0x16e): undefined reference to `curl_easy_setopt'
curl-test-1.c:(.text+0x192): undefined reference to `curl_easy_setopt'
curl-test-1.c:(.text+0x19e): undefined reference to `curl_easy_perform'
curl-test-1.c:(.text+0x1b1): undefined reference to `curl_easy_strerror'
curl-test-1.c:(.text+0x1bd): undefined reference to `curl_easy_cleanup'
/tmp/ccxVQLrA.o: In function `main':
curl-test-1.c:(.text+0x1db): undefined reference to `curl_global_init'
collect2: error: ld returned 1 exit status
Голову ломаю и не пойму, ведь все библиотеки нормально собрались. Почему не видит статическую библиотеку?


Голову ломаю и не пойму, ведь все библиотеки нормально собрались. Почему не видит статическую библиотеку?

Так покажи вывод pkg-config отдельно:

pkg-config --static --libs --cflags /home/user/prg/curl-7.64.1_custom/lib/pkgconfig/libcurl.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libcrypto.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libssl.pc
Deleted
()
Ответ на: комментарий от Deleted

pkg-config разворачивается в

-DCURL_STATICLIB -I/home/user/prg/curl-7.64.1_custom/include -I/home/user/prg/openssl-1.1.1b_custom/include -L/home/user/prg/curl-7.64.1_custom/lib -L/home/user/prg/openssl-1.1.1b_custom/lib -lcurl -lssl -lcrypto -ldl -lcrypto -ldl -lssl -lcrypto -ldl

Пробовал использовать эту строку в команде на компиляцию предварительно удалив дубликаты -lcrypto, -ldl..., результат тот же

ocr
() автор топика
Ответ на: комментарий от ocr

результат тот же

Покажи теперь указанное в выводе содержимое:

ls /home/user/prg/curl-7.64.1_custom/include
ls /home/user/prg/curl-7.64.1_custom/lib
Deleted
()
Ответ на: комментарий от Deleted
├── include
│   └── curl
│       ├── curl.h
│       ├── curlver.h
│       ├── easy.h
│       ├── mprintf.h
│       ├── multi.h
│       ├── stdcheaders.h
│       ├── system.h
│       ├── typecheck-gcc.h
│       └── urlapi.h
├── lib
│   ├── libcurl.a
│   ├── libcurl.la
│   └── pkgconfig
│       └── libcurl.pc
ocr
() автор топика
Ответ на: комментарий от ocr

А теперь в своём тесте попробуй сделать замену:

#include <curl/curl.h>

на

#include "curl/curl.h"

и повторить сборку.

Deleted
()
Ответ на: комментарий от Deleted

уже пробовал в этом направлении, та же ошибка.
Если это поможет,

Linux machine 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3 (2019-02-02) x86_64 GNU/Linux
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)

ocr
() автор топика
Ответ на: комментарий от ocr

Если это поможет

Угадал это не поможет.

Давай проверим инклюд на вшивость:

grep -n curl_easy_init /home/user/prg/curl-7.64.1_custom/include/curl/curl.h
Deleted
()

Что ты несешь? Вали двор мести - это твой потолок.

anonymous
()
Ответ на: комментарий от Deleted

в curl.h его нет, он в easy.h

easy.h:28:CURL_EXTERN CURL *curl_easy_init(void);

там же лежит и в инклюдах которые установлены из репозитория(версия 7.52.1). Проблема в том что линковщик не видит почему-то эти функции при сборке. Попробовал свою кастомную библиотеку:

#objdump --syms libcurl.a | grep easy_init

0000000000000240 g F .text 0000000000000047 .hidden curl_easy_init 0000000000000000 *UND* 0000000000000000 curl_easy_init

ocr
() автор топика
Ответ на: комментарий от ocr

в curl.h его нет, он в easy.h

А в curl.h имеется #include "curl/easy.h"? Причём именно в таком виде?

grep -n "#include" /home/user/prg/curl-7.64.1_custom/include/curl/curl.h
Deleted
()
Ответ на: комментарий от Deleted
/* unfortunately, the easy.h and multi.h include files need options and info
  stuff before they can be included! */
#include "easy.h" /* nothing in curl is fun without the easy stuff */
ocr
() автор топика
Ответ на: комментарий от ocr

#include «easy.h»

Смущает такая постановка пути. Рекомендую указать напрямую:

$ cat curl-test-1.c
...
#include "curl/curl.h"
#include "curl/easy.h"
...

и попробовать собрать снова.

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

А вот была бы у тебя генту, никаких проблем с этим бы не возникло. Каково быть неудачником? :)

Хотя идея всё равно дерьмо, да.

anonymous
()
Ответ на: комментарий от anonymous

Кстати я без проблем собирал в генте под венду, статически. Работало в 7 и 8 так точно (и мб даже в винхп), либц линковалась динамически вендовая правда. И с сертификатами (для https) можно на секс попасть.

anonymous
()
Ответ на: комментарий от ocr

точно так же как и в инклюдах из репы

Чую я, что не удастся заставить ld произвести линковку с помощью флагов. Почему? Хз. Ну так ткни в него объектники напрямую:

cc -Wall --static `pkg-config --static --libs --cflags /home/user/prg/curl-7.64.1_custom/lib/pkgconfig/libcurl.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libcrypto.pc /home/user/prg/openssl-1.1.1b_custom/lib/pkgconfig/libssl.pc` /home/user/prg/curl-7.64.1_custom/lib/libcurl.a curl-test-1.c -o curl-test-1 
Deleted
()
Ответ на: комментарий от Deleted

то же самое. дело не в хидерах, а в том что компоновщик невидит почему-то символов

curl-test-1-2.c:(.text+0xe6): undefined reference to `curl_easy_init'
curl-test-1-2.c:(.text+0x10b): undefined reference to `curl_easy_setopt'
curl-test-1-2.c:(.text+0x12d): undefined reference to `curl_easy_setopt'
curl-test-1-2.c:(.text+0x14f): undefined reference to `curl_easy_setopt'
curl-test-1-2.c:(.text+0x15b): undefined reference to `curl_easy_perform'
curl-test-1-2.c:(.text+0x16e): undefined reference to `curl_easy_strerror'
curl-test-1-2.c:(.text+0x17a): undefined reference to `curl_easy_cleanup'
/tmp/cckR5ZbG.o: In function `main':
curl-test-1-2.c:(.text+0x196): undefined reference to `curl_global_init'
collect2: error: ld returned 1 exit status

ocr
() автор топика
Ответ на: комментарий от ocr

то же самое. дело не в хидерах, а в том что компоновщик невидит почему-то символов

Да я сразу понял, но хотелось, чтобы по красивому. Не получилось, все пути указаны, а архив с объектниками игнорируется. Пробуй на прямую слинковать: Ну так ткни в него объектники напрямую

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

Выкинь дрянь, которая называется PKGCONFIG и линкуй напрямую:

cc --static /home/user/prg/curl-7.64.1_custom/lib/libcurl.a /home/user/prg/openssl-1.1.1b_custom/lib/libcrypto.a /home/user/prg/openssl-1.1.1b_custom/lib/libssl.a curl-test-1.c -o curl-test-1
EXL ★★★★★
()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

Выкинь дрянь, которая называется PKGCONFIG и линкуй напрямую

Согласен, но инклюды надо было оставить. Без них не скомпилится.

Deleted
()
Ответ на: комментарий от EXL

сделал, добавив -DCURL_STATICLIB как указал разраб библиотеки и та же проблема. Добавлял пути к заголовкам openssl и curl, не хочет видеть символы библиотеки. Так же пробовал собрать с libcurl.a которая устанавливается из репы. Похоже что надо собрать это на впс и дать кому-то доступ

ocr
() автор топика
Ответ на: комментарий от ocr

не хочет видеть символы библиотеки

Да он не видит архивы с объектниками (*.a). pkg-config работает с динамической линковкой, но со статикой я его никогда не использовал. Если указать всё напрямую, как указал EXL и указать путь к хедам, всё должно слинковаться:

cc -Wall --static -DCURL_STATICLIB -I/home/user/prg/curl-7.64.1_custom/include -I/home/user/prg/openssl-1.1.1b_custom/include /home/user/prg/curl-7.64.1_custom/lib/libcurl.a /home/user/prg/openssl-1.1.1b_custom/lib/libcrypto.a /home/user/prg/openssl-1.1.1b_custom/lib/libssl.a curl-test-1.c -o curl-test-1
Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от ocr

У меня всё собралось. Собирал так:

gcc curl-test-1.c -o curl-test-1 -DCURL_STATICLIB \
-I/home/exl/Downloads/openssl-1.1.1b_custom/include/ \
-I/home/exl/Downloads/curl-7.64.1_custom/include \
/home/exl/Downloads/curl-7.64.1_custom/lib/libcurl.a \
/home/exl/Downloads/openssl-1.1.1b_custom/libssl.a \
/home/exl/Downloads/openssl-1.1.1b_custom/libcrypto.a \
-ldl

Библиотеку libcurl.a пришлось пересобрать с опциями:

--without-brotli --without-libidn2 --without-nghttp2 --without-libpsl

В противном случае эти либы тоже надо было бы собрать статически.

Сам бинарь зависит лишь от:

$ ldd curl-test-1
        linux-vdso.so.1 (0x00007fff88310000)
        libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fa4501b2000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007fa44ffee000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fa4504ce000)

Х.з., возможно ли его сделать полностью статическим, учитывая всякие там getaddrinfo/gethostbyname/getpwuid_r и пр., видимо для этого нужно ещё и Glibc пересобирать.

Удачи!

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

Огромное вам человечье спасибо, zvezdochiot и EXL, все собралось, а причиной проблем была НЕПРАВИЛЬНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ ПАРАМЕТРОВ, я их вообще не брал в расчет, буду курить маны.

ocr
() автор топика
Ответ на: комментарий от ocr

Да, GCC’шный линкер глуповат и не умеет строить дерево зависимостей, поэтому порядок линковки библиотек важен.

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

Выкинь дрянь, которая называется PKGCONFIG и линкуй напрямую

в этом свете, не такая уж и дрянь этот pkg-config, если б линковщик gcc мог строить валидное дерево

ocr
() автор топика
Ответ на: комментарий от ocr

В .pc файлах обычно забивают на поддержку static libs, поэтому работает оно не очень

anonymous
()
Ответ на: комментарий от ocr

если б линковщик gcc мог строить валидное дерево

Вроде он умеет его строить через опции -Wl,--start-group и -Wl,--end-group, но скорее всего только на последних версиях и это отключено по умолчанию.

А pkg-config дрянь потому что он не является кроссплатформенным.

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

под винду есть (mingw), под макось есть, для андроида всё равно кроссконпеляция используется, так что тоже есть

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

под винду есть (mingw)

Это не нативно.

под макось есть

Это не нативно.

для андроида всё равно кроссконпеляция используется, так что тоже есть

И в Android NDK нет pkg-config, но есть, например, CMake.

EXL ★★★★★
()
Ответ на: комментарий от fsb4000

Я знаю, но с MS Visual Studio и мелкософтовскими компиляторами это нормальным образом не сопрягается. А CMake, например, сопрягается.

EXL ★★★★★
()
Ответ на: комментарий от Harald

зато в хост-системе есть

Хост системой для Android-разработки может быть и не Linux. Если ты завяжешься на pkg-config то твой Android-проект хрен соберётся на macOS или Windows.

В Android NDK не зря убили всякие там убогие autotools, libtool и прочее вроде pkg-config.

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

не зря убили всякие там убогие autotools, libtool и прочее вроде pkg-config.

А что не так с cmake? Всё пилят и пилят, и изменения синтаксиса всё время, как будто из одного края в другой прыгают. Что не так? Во что упёрлись девелопмеры cmake?

Deleted
()
Ответ на: комментарий от Deleted

А что не так с cmake?

Он просто хреновый, хоть и сделался устоявшимся стандартом. Можно было сделать лучше. Можно было сделать нормальный язык, декларативный DSL. Можно было сделать регистрозависимость, чтобы сборочные рецепты не вызывали рвоту. Можно было изящно обойти все вот эти описанные проблемы: За что так не любят cmake? (комментарий).

Можно было и дальше продолжать бандлить в дистрибутив CMake-модули для либ, а не развернуться на полпути и сказать пок-пок-пок: Оценки хелловорлда тред (комментарий). Ну или хотя бы сделать вменяемый репозиторий, который бы содержал CMake-модули для библиотек.

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

сделался устоявшимся стандартом

Так об этом и вопрос. Версия 2.8 ещё ощущается как некий стандарт. А всё, что дальше, в понятие «стандарт» укладывается очень плохо. Скорее не «стандарт», а «фитчи».

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

В последних версиях CMake подтянули к более-менее человеческому виду. А вот пользоваться 2.8 было трудновато без написания кучи костылей.

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

Если ты завяжешься на pkg-config то твой Android-проект хрен соберётся на macOS или Windows.

почему меня это должно беспокоить

тем не менее, соберётся, если приложить усилия

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

тем не менее, соберётся, если приложить усилия

Это называется пердолинг.

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

И в Android NDK нет pkg-config, но есть, например, CMake.

CMake, между прочим, тоже может использовать pkg-config для поиска зависимостей

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

Да, если ты хочешь завязаться на Linux-like окружение only.

EXL ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.