gcc -Wl,--as-needed ...

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 18 авг 2016, 16:17

Проблема была в 1-й раз описана здесь - Mint.

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ lsb_release -ircd
Distributor ID: LinuxMint
Description:    Linux Mint 17.1 Rebecca
Release:        17.1
Codename:       rebecca
Собираем простейшую программу ... сложности порядка Hello World! - файл ex1.c

Код: Выделить всё

#include <stdio.h>
#include <math.h>

int main( void ) {
   float d = 9;
   printf( "%f\n", sqrt( d ) );
   return 0;
}
И надеемся, что уж с такой то программой мы справимся...
Ага ... ща-а-а-аз:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall -lm ex1.c -o ex1
/tmp/ccUuI8Fy.o: In function `main':
ex1.c:(.text+0x1a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Но стоит поменять местами опции gcc - и всё срабатывает:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall ex1.c -lm -o ex1

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ ./ex1
3.000000
И ещё одна особенность - если то же собирать как приложение C++:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ g++ -lm -Wall ex1.c -o ex1++

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ ./ex1++
3.000000
Это не зависит а). ни от версии gcc, б). ни от разрядности системы 32/64...
А зависит это ... от используемого дистрибутива Linux! :-o
Это не возникает в: Fedora, CentOS, Debian ... и даже Rosa, Mageia.
Это возникает в: Ubuntu (со всеми их разнообразными Xubuntu, Lubuntu, Kubuntu...), Mint, Gentoo, ALT Linux.
Не знаю, каким ещё дистрибутивам это свойственно.
Вложения
ex1.c
(120 байт) 190 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 18 авг 2016, 17:00

Olej писал(а): А зависит это ... от используемого дистрибутива Linux! :-o
Проблема, в общем, известная.
Интернет полнится криками: "Help!". :cry: :evil:
Но в ... организованной литературе (книги, статьи, ...) я никогда не встречал даже упоминания проблемы.
Но если с ней столкнуться и быть неготовым ... много крови может попить! :(
Особенно когда это сборка чужого проекта с готовым и объёмным Makefile (или ./configure), подготовленным в другой системе.
И уж не говоря про сборку с помощью CMake (вдруг кому такая глупость взбредёт), которую в таких случаях, предполагаю, или просто невозможно корректно описать в CMakeLists.txt, или очень искусственно нужно изощряться ... и долго. :cry:

Происхождение, природа проблемы мне известна.
И её преодоление ... на 50-70% случаев - известны.
О подобном достаточно много писали и обсуждали ещё в AltLinux времён 2008 года и в некоторых Fedora того же периода.
http://www.linux.org.ru/forum/development/3104129
http://www.linux.org.ru/forum/development/2729273
https://bugzilla.altlinux.org/show_bug.cgi?id=15584
Причина объясняется как сборка ld (gcc) с желанием экономить до 5% времени работы :lol: :lol: :lol: - вот здесь подробно. Там подробно описывается когда и почему это возникает...
В любом случае, технически достаточно просто записывать библиотеки в команде gcc позже, чем объектные файлы их использующие.
Но это не всегда возможно, особенно при сборке чужих проектов.

Проблема тянет за собой ряд вопросов:
- как точно определить (предполагать) что в вашем проекте (в вашей системе) это может выявиться?
- как её устранить ... в тех случаях, которые не подпадают под вот те 50-70% случаев?
- почему это не проявляется при использовании g++, C++ ?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 18 авг 2016, 17:04

Olej писал(а): Интернет полнится криками: "Help!". :cry: :evil:
edited Apr 10 '14 at 21:00
Вот, например, интересно - gcc --as-needed linker flag not working
I have two computers with Gentoo, both on AMD64. I try to build a following program:

Код: Выделить всё

int main() {tgetent();}
The command to compile is:
gcc -v 1.c -Wl,--as-needed -lncurses
On one computer it cannot find the function while on the other one it can. Without --as-needed flag it links properly. The versions of the compilers and binutils are the same.
Ответ ... который мне кажется достаточно пустым :-? :
gcc is really a controller which runs compiler (cc) and linker (ld) in order. It passes -W options to the linker. You might try compiling with gcc, but then linking by hand to test this, suggest 'ld --trace --verbose --as-needed -lncurses 1.o -o 1' (after 'gcc 1.c -o 1.o') Placement of '-lncurses' in cmdline MAY affect success, see ld man pages on -l option and location in line effects.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 19 авг 2016, 14:46

Olej писал(а):Это не зависит а). ни от версии gcc, б). ни от разрядности системы 32/64...
А зависит это ... от используемого дистрибутива Linux! :-o
Некоторые детали (но не все) этой проблемы я буду обсуждать на ФОРУМ ДЛЯ LINUX ПОЛЬЗОВАТЕЛЕЙ ... особенно когда там задают вопросы ;-) .
То, что там будет актуальным - буду переписывать сюда:
Разговор вот о чём:

- во многих дистрибутивах Linux, но не во всех...

- сборка пакета gcc выполняется так, что используемые библиотеки в командной строке должны указываться после указания объектных файлов, которые их исользуют

- например:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall ex1.c -lm -o ex1 
Вот это было ОК
А вот это даёт ошибку:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall -lm ex1.c -o ex1 
/tmp/ccDl3g6B.o: In function `main':
ex1.c:(.text+0x1a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Это делается для того, чтобы (якобы) не подключались библиотеки DLL, которые указаны в командной строке, но на которые нет ссылок из объектных файлов. (А указание исходных файлов .c только маскирует ситуацию - после их компиляции на их месте окажутся объектные - и делает сообщения об ошибках ещё более загадочными для тех, кто не знает и не предполагает здесь подвоха).
Такое поведение не требует загрузки этих библиотек при исполнении и даёт экономию ... как показали более поздние исследования порядка 4.5% :?
Но в погоне за рыночной привлекательностью (вот мы якобы лучше других :lol: ) некоторые стали собирать GCC именно так.

В связи с этим в GCC и появилась новая опция (линковщика) -Wl,--as-needed (которая вынесена в заголовок): не подключать библиотеки, на которые нет ссылок из объектных файлов.
Об этом достаточно много обсуждений ... и стонов в Интернет (стонов, главным образом, от тех кто не знает и не понимает что за опция -Wl,--as-needed).
Опция -Wl,--as-needed есть во всех дистрибутивах.
Это опция самого GCC.
И может быть полезной, если нею умело распорядиться.
Опция и вот этот эффект, связанный с жёстким порядком указания библиотек в командной строке - это разные вещи.
Хотя у них и общая природа: желание исключить из сборки не используемые библиотеки.
Откуда у меня возникло по-новой разбирательство с этой проблемой?
Меня попросили проект с Makefile (который я раньше и сделал) переписать под сборку CMake.
И вот, у меня на Fedora проект собирается, а у клиента на Ubuntu - ни фига ... с тяжелейшими и не диагностируемыми ошибками.
В итоге, полагаю, под некоторыми дистрибутивами проекты на языке C с помощью CMake вообще невозможно будет собрать (гипотеза :D ).
Потому как параметры сборки там в CMakeLists.txt вы определяете спец. макросами типа:

Код: Выделить всё

execute_process(COMMAND net-snmp-config --agent-libs
                OUTPUT_VARIABLE LDOPT
               )
string(STRIP "${LDOPT}" CMAKE_EXE_LINKER_FLAGS)
А куда он потом втулит этот $CMAKE_EXE_LINKER_FLAGS, в начало или в хвост командной строки - это его дело, и контролировать вы это никак не сможете.
И так со всем великим множеством переменных CMake.

P.S. Резюме ... попутно возникшее (и сформулированное мной заказчику :D ): а не надо пользоваться всякими приблудами для сборки :evil: , типа CMake (и QtCreator) ... или всякими "проектами", которые строят некоторые разные IDE - это всё идёт от дурных манер Windows и MS VisualStudio. А нужно пользоваться Makefile. ;)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 19 авг 2016, 22:03

Olej писал(а): - как её устранить ... в тех случаях, которые не подпадают под вот те 50-70% случаев?
Один из способов решения:

Код: Выделить всё

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ lsb_release -ircd
Distributor ID: LinuxMint
Description:    Linux Mint 17.1 Rebecca
Release:        17.1
Codename:       rebecca

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall -lm ex1.c -o ex1
/tmp/ccUuI8Fy.o: In function `main':
ex1.c:(.text+0x1a): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Обсуждаемый эффект наблюдается.
А теперь смотрим сюда:

Код: Выделить всё

olej@nvidia / $ ls -l `which ld`*
lrwxrwxrwx 1 root root       6 мая    2 23:41 /usr/bin/ld -> ld.bfd
-rwxr-xr-x 1 root root 1042556 мая    2 23:40 /usr/bin/ld.bfd
-rwxr-xr-x 1 root root    5424 мая   26 13:39 /usr/bin/ldd
-rwxr-xr-x 1 root root 2513280 мая    2 23:40 /usr/bin/ld.gold
-rwxr-xr-x 1 root root      87 февр. 16  2014 /usr/bin/ld-musl-config

olej@nvidia / $ ld.bfd --version
GNU ld (GNU Binutils for Ubuntu) 2.24
Copyright 2013 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

olej@nvidia / $ ld.gold --version
GNU gold (GNU Binutils for Ubuntu 2.24) 1.11
Copyright 2013 Free Software Foundation, Inc.
Данная программа является свободным программным обеспечением;  вы можете распространять её в соответствии
с условиями GNU General Public License Версия 3 или (на ваш выбор) более поздней версии.
Эта программа не имеет абсолютно никаких гарантий.

Как легко видеть, это два разных компоновщика.

Код: Выделить всё

olej@nvidia /usr/bin $ sudo ln -sf /usr/bin/ld.gold /usr/bin/ld

olej@nvidia ~/2016_WORK/in.WORK/as-needed $ gcc -Wall -lm ex1.c -o ex1
Сменили компоновщик ld.bfd на ld.gold.
Теперь всё срабатывает без проблем.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 19 авг 2016, 22:16

Olej писал(а): Сменили компоновщик ld.bfd на ld.gold.
Компоновщик ld в будущем будет заменен компоновщиком gold
24.03.2008 13:41:43
Ян Тейлор (Ian Taylor) представил новый компановщик gold, работающий до 5 раз быстрее прежнего ld. Код уже добавлен в GNU binutils, однако все еще имеет статус бета, т.к. тестировался только внутри Google, пока поддерживает архитектуры x86 и x86_64 (легко портируется) и формат ELF (поддержка других форматов не планируется).
gold
15:56, 23 марта 2013
gold — новый линковщик (пришедший на смену существующему GNU ld), разработанный Яном Тэйлором (Ian Taylor). Интегрирован в binutils начиная с 2.18 (но по умолчанию не используется). Призван ускорить сборку программ (особенно C++); скорость линковки повышается иногда значительно, вплоть до пятикратной.
...
Пока что gold обычный ld не заменит (и не факт, что заменит в будущем), поэтому хорошо иметь возможность выбора между ними (например, для того чтобы использовать gold при разработке и обычный ld для релизов).

Хуже всего, что у gcc нет опций командной строки, с помощью которых можно было бы явно указать, какой линковщик мы используем. Есть несколько вариантов решения:
...
gold (компоновщик)
gold — это компоновщик для ELF файлов. Он стал официальным пакетом GNU[1] и был добавлен в binutils в марте 2008 года[2] [3] и был впервые выпущен в составе binutils версии 2.19. Gold был разработан Йеном Лэнсом Тейлором и небольшой командой из Google.[4] Мотивацией для написания gold было создание компоновщика, который является более быстрым, чем GNU linker, особенно для больших приложений, написанных на C++.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 19 авг 2016, 22:52

Olej писал(а): Сменили компоновщик ld.bfd на ld.gold.
Теперь всё срабатывает без проблем.
Немного по-другому всё это происходит, например, в Fedora:

Код: Выделить всё

[olej@dell as-needed]$ cat ld.hist 
[olej@dell as-needed]$ lsb_release -ircd
Distributor ID:	Fedora
Description:	Fedora release 23 (Twenty Three)
Release:	23
Codename:	TwentyThree

[olej@dell ~]$ ls -l /usr/bin/ld*
lrwxrwxrwx. 1 root root      20 апр 22 12:56 /usr/bin/ld -> /etc/alternatives/ld
-rwxr-xr-x. 1 root root  913576 мар  1 10:53 /usr/bin/ld.bfd
-rwxr-xr-x. 1 root root    5441 июн  2 14:09 /usr/bin/ldd
-rwxr-xr-x. 1 root root 5444640 мар  1 10:53 /usr/bin/ld.gold

[olej@dell ~]$ ls -l /etc/alternatives/ld
lrwxrwxrwx. 1 root root 15 апр 22 12:56 /etc/alternatives/ld -> /usr/bin/ld.bfd

[olej@dell ~]$ ld.bfd --version
GNU ld version 2.25-17.fc23
Copyright (C) 2014 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

[olej@dell ~]$ ld.gold --version
GNU gold (version 2.25-17.fc23) 1.11
Copyright (C) 2014 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

Код: Выделить всё

[olej@dell as-needed]$ gcc -Wall -Wl,--as-needed -lm ex1.c -o ex1
/tmp/ccBl4XdL.o: In function `main':
ex1.c:(.text+0x1b): undefined reference to `sqrt'
collect2: ошибка: выполнение ld завершилось с кодом возврата 1
Здесь тоже можно сменить ссылку, но есть куда более элегантное решение:

Код: Выделить всё

[olej@dell as-needed]$ sudo alternatives --config ld
[sudo] пароль для olej: 

Имеется 2 программ, которые предоставляют 'ld'.

  Выбор    Команда
-----------------------------------------------
*+ 1           /usr/bin/ld.bfd
   2           /usr/bin/ld.gold

Enter - сохранить текущий выбор[+], или укажите номер: 2


[olej@dell as-needed]$ alternatives --display ld
ld - статус "вручную"
 ссылка сейчас указывает на /usr/bin/ld.gold
/usr/bin/ld.bfd - priority 50
/usr/bin/ld.gold - priority 30
Текущая `лучшая' версия - /usr/bin/ld.bfd.

[olej@dell as-needed]$ gcc -Wall -Wl,--as-needed -lm ex1.c -o ex1

[olej@dell as-needed]$ gcc -lm -Wall -Wl,--as-needed ex1.c -o ex1

[olej@dell as-needed]$ ./ex1
3.000000
Как видно, для ld.gold даже при опции -Wl,--as-needed порядок указания входных источников не важен.
Таким же точно образом (sudo alternatives --config ld) можно мгновенно сменить ld на ld.bfd.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 19 авг 2016, 23:44

Olej писал(а): - почему это не проявляется при использовании g++, C++ ?
На C++ всё поведение точно так же:

Код: Выделить всё

[olej@dell as-needed]$ alternatives --display ld
ld - статус "вручную"
 ссылка сейчас указывает на /usr/bin/ld.bfd
/usr/bin/ld.bfd - priority 50
/usr/bin/ld.gold - priority 30
Текущая `лучшая' версия - /usr/bin/ld.bfd.

[olej@dell as-needed]$ g++ -std=gnu++11 -Wl,--as-needed -o ex2 ex2.cc -lpcre

[olej@dell as-needed]$ g++ -std=gnu++11 -Wl,--as-needed -lpcre -o ex2 ex2.cc
/tmp/cc02ATVb.o: In function `main':
ex2.cc:(.text+0x5e): undefined reference to `pcre_compile'
ex2.cc:(.text+0xe9): undefined reference to `pcre_exec'
collect2: ошибка: выполнение ld завершилось с кодом возврата 1
А на простейшем примере с ex1 не наблюдается эффект только потому, что к команде линковки g++ по умолчанию добавляет -lstdc++ с зависимостями (включая -lm), и делает это в конце командной строки.

P.S. файл ex2.cc ... что там происходит - не важно (это поиск по регулярному выражению в стиле Perl), важно что это нужно связать с библиотекой libpcre.so :

Код: Выделить всё

#include <iostream>
#include <cstring>
#include <pcre.h>

int main(int argc, char **argv) {
    pcre *re;
    const char *err;
    int erroffset;
    if (argc != 3) {
        std::cerr << "specify exactly 2 arguments" << std::endl;
        return 1;
    }
    re = pcre_compile(argv[1], 0, &err, &erroffset, nullptr);
    if (! re) {
        std::cerr << erroffset << ": " << err << std::endl;
        return 2;
    }
    if (pcre_exec(re, nullptr, argv[2], strlen(argv[2]), 0, 0, nullptr, 0) != PCRE_ERROR_NOMATCH) {
        std::cout << argv[2] << std::endl;
    }
    return 0;
}
Вложения
ex2.cc
(583 байт) 187 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 20 авг 2016, 01:08

Olej писал(а): gold
АНАЛИЗ ПЕРСПЕКТИВ ВНЕДРЕНИЯ КОМПОНОВЩИКА GOOGLE GOLD В ПРОГРАММНЫЕ ПРОДУКТЫ НА C++
Авторы:
Иванов Е.Ю.
Шагал А.А.
Город:
Санкт-Петербург
ВУЗ:
Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики
Дата:
11 мая 2016г.
С целью уменьшить время компоновки в качестве замены GNU ld компания Google разработала компоновщик gold. В отличие от ld, работающего с разными форматами исполняемых файлов, в частности ELF, a.out и COFF, gold поддерживает только формат ELF, что скорее всего позволило разработчикам сосредоточиться на быстродействии, а не универсальности. Другой особенностью gold является многопоточность. Согласно заявлениям разработчиков Google, использование компоновщика gold позволяет уменьшить время компиляции отдельных программ на C++ от двух до пяти раз по сравнению c GNU ld [3], при этом не уточняется, в каких конкретно случаях достигается подобное преимущество.
Однако при компиляции больших программных продуктов на С++ использование компоновщика gold позволяет уменьшить среднее время компиляции не более, чем на 2% вне зависимости от скорости операций ввода-вывода. Это объясняется тем, что на время компиляции больших продуктов в большей степени влияет время трансляции и оптимизации.
(всё где выделено - это мной)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: gcc -Wl,--as-needed ...

Непрочитанное сообщение Olej » 10 авг 2022, 23:48

Olej писал(а):
18 авг 2016, 16:17
Проблема была в 1-й раз описана здесь
Снова вылезла та же проблема ... через 6 лет после её здесь обнаружения - здесь: файловая система FUSE.
Такое же может вылезать на самых разных типовых проектах прошлых лет, которые до это собиралисб "на ура".
Об этом нужно помнить!

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей