Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225

GNU/Linux Qt5.* - Линкуем статически

23.01.2014, 19:10. Показов 145912. Ответов 62
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В связи с отсутствием в данной теме мануала по статической линковке приложений Qt, решил исправить данный недостаток
Оговорюсь сразу: приветствуется беспощадная критика, особенно, что касается скриптов)
Итак:
1) Как обычно, нужно пересобрать фреймвор статически. Для этого скачиваем архив с исходными текстами отсюда: http://qt-project.org/downloads
На данный момент имя тар-бола - qt-everywhere-opensource-src-5.2.0.tar.gz

2) Переходим в каталог с тар-болом. Разархивируем и распаковываем. Потом нужно сконфигурировать, собрать и установить тонну исходников. Делаем это так ( за дополнительными параметрами, если нужно, обращайтесь ./configure --help):
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tar -xzvf qt-everywhere-opensource-src-5.2.0.tar.gz && cd qt-everywhere-opensource-src-5.2.0 \
&& sudo mkdir -p /usr/lib/Qt5_static && ./configure -platform linux-g++ \
-release \
-static \
-fontconfig \
-opensource \
-confirm-license \
-nomake examples \
-c++11 \
-nomake tests \
-qt-zlib \
-qt-libpng \
-qt-libjpeg \
-prefix /usr/local/Qt5_static \
&& make -j3 && make install
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Объяснение опций:
-platform linux-g++ \ # Ваша платформа и компилятор
-release \ # Собираем для релиза
-static \ # Собственно, наша цель собрать статически
-fontconfig \ # Поддержка собственного fontconfig
-opensource \ # СПО версия
-confirm-license \ # Сразу согласиться с лицензией
-nomake examples \ # Не собирать учебные примеры
-c++11 \ # Поддержка последнего стандарта
-nomake tests \ # Не проводить тесты
-qt-zlib \ # Внедрение собственной библиотеки <libname>
-qt-libpng \ # ...
-qt-libjpeg \ # ...
-prefix /usr/local/Qt5_static \ # Относительно этого пути будет производиться установка (можете свой указать)
make -j3 # количество ядер процессора +1
3) Так, теперь у нас есть все необходимые инструменты (почти )
Заходим в QtCreator, Tools > Options > Build & Run > Qt Versions
Добавляем путь к новому qmake ( в нашем случае /usr/local/Qt5_static/bin/qmake ).
Затем идем на вкладку Kits и добавляем новый набор инструментов, только укзываем ему qmake, только что добавленный на предыдущем шаге. Озаглавим этот набор Qt5_staticKit, например. Нажимаем Ok.
4) Ctrl+5, выбираем вверху проект, который мы хотим собрать статически, и щелкаем по новому Kit'y Qt5_staticKit. Выбираем Release конфигурацию. Тааак, здесь пока все.
5) Перелазим в .pro file. Добавляем туда
Code
1
2
3
QMAKE_LFLAGS += -s # Убрать все таблицы символов из результирующего бинарника ( man gcc )
# 3-rd party библиотеки, (boost, gmp, ... ) если есть статический вариант добавляем так:
LIBS += -Wl, -Bstatic, -lboost_regex, -lgmp, -lgmpxx, -Bdynamic
Теперь все Qt и 3-rd party библиотеки сидят в бинарнике, НО дело еще не закончено.
Если посмотреть на вывод ldd, то можно увидеть, что приложение зависит еще от целой кучи не Qt-ных библиотек. Они могут быть бинарно-несовместимыми со своими предыдущими версиями (особенно, если написаны на С++) даже если они имеются на чужом компьютере.
Например:
Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ldd traditional
        linux-vdso.so.1 (0x00007fffd05fe000)
        libgobject-2.0.so.0 => lib/libgobject-2.0.so.0 (0x00007fe1a298a000)
        libX11-xcb.so.1 => lib/libX11-xcb.so.1 (0x00007fe1a2788000)
        libXi.so.6 => lib/libXi.so.6 (0x00007fe1a2578000)
        libxcb-render-util.so.0 => lib/libxcb-render-util.so.0 (0x00007fe1a2375000)
        libSM.so.6 => lib/libSM.so.6 (0x00007fe1a216d000)
        libICE.so.6 => lib/libICE.so.6 (0x00007fe1a1f51000)
        libxcb-glx.so.0 => lib/libxcb-glx.so.0 (0x00007fe1a1d39000)
        libxcb-render.so.0 => lib/libxcb-render.so.0 (0x00007fe1a1b2f000)
        libxcb-keysyms.so.1 => lib/libxcb-keysyms.so.1 (0x00007fe1a192d000)
        libdbus-1.so.3 => lib/libdbus-1.so.3 (0x00007fe1a16e5000)
        libxcb.so.1 => lib/libxcb.so.1 (0x00007fe1a14c5000)
        libxcb-image.so.0 => lib/libxcb-image.so.0 (0x00007fe1a12c1000)
        libxcb-icccm.so.4 => lib/libxcb-icccm.so.4 (0x00007fe1a10bd000)
        libxcb-sync.so.1 => lib/libxcb-sync.so.1 (0x00007fe1a0eb7000)
        libxcb-xfixes.so.0 => lib/libxcb-xfixes.so.0 (0x00007fe1a0cb0000)
        libxcb-shm.so.0 => lib/libxcb-shm.so.0 (0x00007fe1a0aad000)
        libxcb-randr.so.0 => lib/libxcb-randr.so.0 (0x00007fe1a089f000)
        libxcb-shape.so.0 => lib/libxcb-shape.so.0 (0x00007fe1a069b000)
        libxcb-xkb.so.1 => lib/libxcb-xkb.so.1 (0x00007fe1a0480000)
        libxkbcommon.so.0 => lib/libxkbcommon.so.0 (0x00007fe1a0220000)
        libfontconfig.so.1 => lib/libfontconfig.so.1 (0x00007fe19ffe4000)
        libfreetype.so.6 => lib/libfreetype.so.6 (0x00007fe19fd3f000)
        libXrender.so.1 => lib/libXrender.so.1 (0x00007fe19fb35000)
        libXext.so.6 => lib/libXext.so.6 (0x00007fe19f923000)
        libX11.so.6 => lib/libX11.so.6 (0x00007fe19f5e8000)
        libudev.so.1 => lib/libudev.so.1 (0x00007fe19f3d6000)
        libicui18n.so.52 => lib/libicui18n.so.52 (0x00007fe19efce000)
        libicuuc.so.52 => lib/libicuuc.so.52 (0x00007fe19ec55000)
        libpcre16.so.0 => lib/libpcre16.so.0 (0x00007fe19e9f6000)
        libdl.so.2 => lib/libdl.so.2 (0x00007fe19e7f2000)
        libgthread-2.0.so.0 => lib/libgthread-2.0.so.0 (0x00007fe19e5f0000)
        libglib-2.0.so.0 => lib/libglib-2.0.so.0 (0x00007fe19e2f0000)
        librt.so.1 => lib/librt.so.1 (0x00007fe19e0e8000)
        libGL.so.1 => lib/libGL.so.1 (0x00007fe19ddb5000)
        libpthread.so.0 => lib/libpthread.so.0 (0x00007fe19db98000)
        libstdc++.so.6 => lib/libstdc++.so.6 (0x00007fe19d894000)
        libm.so.6 => lib/libm.so.6 (0x00007fe19d591000)
        libgcc_s.so.1 => lib/libgcc_s.so.1 (0x00007fe19d37b000)
        libc.so.6 => lib/libc.so.6 (0x00007fe19cfd1000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe1a2bdb000)
        libpcre.so.1 => lib/libpcre.so.1 (0x00007fe19cd6a000)
        libffi.so.6 => lib/libffi.so.6 (0x00007fe19cb62000)
        libuuid.so.1 => lib/libuuid.so.1 (0x00007fe19c95d000)
        libXau.so.6 => lib/libXau.so.6 (0x00007fe19c759000)
        libXdmcp.so.6 => lib/libXdmcp.so.6 (0x00007fe19c553000)
        libxcb-util.so.1 => lib/libxcb-util.so.1 (0x00007fe19c34e000)
        libexpat.so.1 => lib/libexpat.so.1 (0x00007fe19c124000)
        libz.so.1 => lib/libz.so.1 (0x00007fe19bf0e000)
        libbz2.so.1.0 => lib/libbz2.so.1.0 (0x00007fe19bcfe000)
        libpng16.so.16 => lib/libpng16.so.16 (0x00007fe19bac9000)
        libicudata.so.52 => lib/libicudata.so.52 (0x00007fe19a25e000)
        libnvidia-tls.so.331.38 => lib/libnvidia-tls.so.331.38 (0x00007fe19a05b000)
        libnvidia-glcore.so.331.38 => lib/libnvidia-glcore.so.331.38 (0x00007fe19784d000)

Пересобирать каждую из них, в случае, когда нет статической, довольно проблематично и долго и не всегда возможно ( кто хочет пусть попробует ), поэтому есть вариант поставлять их вместе со своим приложением. Большая вероятность того, что большинство этих библиотек будут на чужой машине, но выполнив еще немного действий, вы застрахуете и себя, и пользователя от лишней головной боли.
Вот что делаем:
1) Нужно скопировать симлинк, который выводит ldd, и библиотеку на которую он указывает в каталог с нашим приложением. ( в нашем случае /path/to/app/lib ). Симлинк использует динамический загрузчик при загрузке библиотеки для приложения во время выполнения, ну а библиотека, на которую он указывает это собственно данные.

Вот наваял такой скрипт (еще раз напомню, что правки и улучшения очень приветствуются c башем знаком 2 дня )

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/bin/sh
LIB_DIR=lib/
SONAME_LIST=soname.lst
 
if [ "$#" -lt 1 ]; then
    echo "Usage: ./$(basename ${0}) < executable >"
    exit 1;
fi
 
# slc.c: На входе - вывод ldd, на выходе - имена symlink'ов, для динамич. загрузчика
cat<<'EOF' > slc.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <locale.h>
    #include <string.h>
 
    #define MAX_LENGTH 256
    #define LINE_CNT 200
    int first_nonspace(const char *s) {
    for(size_t i=0; *s; ++i, ++s)
        if( !isspace(*s) )
        return i;
    return -1; // Нет значимых символов
    }
    int main() {
    setlocale(LC_ALL, "C");
    char** lines = malloc( LINE_CNT * sizeof(char*) );
    for(int i=0; i < LINE_CNT; ++i)
        lines[i] = malloc( MAX_LENGTH * sizeof(char) );
    char  line[MAX_LENGTH];
    size_t currLineNumb = 0;
 
    while( fgets(line, MAX_LENGTH, stdin) != NULL && currLineNumb < LINE_CNT) {
        int fns = first_nonspace(line);
        if(fns == -1)
        continue;
        else {
        char lib_prefix[4] = {'\0',}; // "lib" + '\0'
        strncpy(lib_prefix, line+fns, 3);
        lib_prefix[3] = '\0';
        if( !strcmp(lib_prefix, "lib")) // Если имя начинается с 'lib',
            strcpy(lines[currLineNumb++], line+fns); // сохраняем эту строчку
        }
    }
    // Выводим сохраненную строчку до первого пробела,
    // что и будет составлять наш soname.
    for(size_t i=0; i < currLineNumb; ++i)
        printf("%.*s\n", (int)(strchr(lines[i], ' ') - lines[i]), lines[i]);
    for(int i=0; i < LINE_CNT; ++i) free(lines[i]);
    free(lines);
    return 0;
    }
EOF
cc -std=c99 slc.c -o slc
mkdir -p ${LIB_DIR}
ldd $1 | ./slc > $SONAME_LIST
for name in `cat $SONAME_LIST`; do
    libname=$(readlink /usr/lib/$name)   # Получим имя библиотеки
    cp /usr/lib/${libname} -t $LIB_DIR;    # Копируем библиотеку
    cp -P /usr/lib/${name} -t $LIB_DIR;    # Копируем симлинк, нужный для ldd
done
 
# Чистимся
rm -f ${SONAME_LIST} slc{,.c}
exit 0;
Сохраняем это под именем, например, s.sh, и ложим в каталог с исполняемым файлом приложения.
Выполняем:
Bash
1
chmod +x s.sh && ./s.sh name_of_the_executable
В текущем каталоге появится каталог ./lib/ , в котором будут лежать все необходимые ссылки и библиотеки.
Последний штрих: в .pro файл нужно добавить -rpath опцию линковщику, чтобы загрузчик потом знал, что поставляемые нами вместе с приложением библиотеки лежат в папке lib/ (в данном случае):
Code
1
LIBS += -Wl,-rpath lib/
Теперь все это дело в .tar.gz и можете делиться с друзьями своим приложением

Как из этого сделать программный пакет, смотрите документацию к своему дистрибутиву GNU/Linux.

Ps. На MacOS процедура практически не должна отличаться, но у меня нет возможности проверить.
Pss. Если ваше приложени базируется на плагинах, то они по своей природе не могут линковаться статически..
Смотрите документацию http://qt-project.org/doc/qt-4... t-x11.html и все вытекающие перекрестные ссылки по плагинам.
________________________________________ ________________________________________ ___________________________
Вроди бы ничего не забыл...
Надеюсь, статейка кому-нибудь поможет разобраться.
Спасибо и удачи
6
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.01.2014, 19:10
Ответы с готовыми решениями:

Timestamp->QdateTime (Qt5+Firebird+Linux)
Направьте на путь истинный. В исходниках Qt5 есть небольшой пример, sqlbrowser. И есть база FB. Всё коннектится и показывается. Но есть...

Qt5 перенос приложения из windows7 в linux (Raspbery)
Добрый вечер! Извиняюсь, не так давно знаком с Qt и линукс, нужна помощь. Задача стоит разработать приложение для микрокомпьютера...

Удаление GNU\Linux из автозагрузки Kali Linux x64
Здравствуйте. Установил криво Kali Linux на диск С. Потом удалил все его файлы. Но в автозагрузке Linux Осталась не могу удалить. И можно...

62
-1 / 5 / 2
Регистрация: 13.03.2013
Сообщений: 203
11.03.2018, 21:23
Студворк — интернет-сервис помощи студентам
RazrFalcon,
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 #!/bin/sh
LIB_DIR=lib/
 
if [ "$#" -lt 1 ]; then
    echo "Usage: ./$(basename ${0}) < executable >"
    exit 1;
fi 
 
mkdir -p ${LIB_DIR}
#забираем все пути
SONAME_LIST=`ldd "$1" | sed 's/^.*> //g;s/ (.*//g;s/\t//g'`
for name in $SONAME_LIST; do
    # игнорируем некоторые либы
    if [ $name != "linux-vdso.so.1" ]; then
        linkname=`readlink $name`
        # не пытаемся копировать либы у которых нет симлинков
        if [ -n "$linkname" ]; then
            cp `dirname $name`"/"$linkname -t $LIB_DIR;
        fi
        cp -P ${name} -t $LIB_DIR;
    fi
done
Почему-то копируется часть не библиотек , а "ссылка на разделяемая библиотека". Так и надо?
0
Just Do It!
 Аватар для XLAT
4220 / 2684 / 656
Регистрация: 23.09.2014
Сообщений: 9,236
Записей в блоге: 3
22.11.2020, 13:17
8Observer8,
10 экранов примерно таких варнингов:


и неверное автоопределение директории источника:
1
2 / 1 / 1
Регистрация: 19.05.2015
Сообщений: 14
07.04.2021, 23:48
Вот ещё до кучи ликбез по статической сборке Qt 5.15
https://habr.com/ru/post/549886/
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.04.2021, 23:48

Знакомство с GNU/Linux
требуется объединить содержимое 2-х файлов,например task1.cpp и task3.cpp в единый новый файл и провести его компиляцию. Пробовала...

Отличие freeBSD от GNU/Linux
Доброй ночи это одно и тоже. Просто пишут иногда что подходит как для FreeBSD так и для Linux. Получается есть отличие. В чем оно?

Удаление GNU\Linux из автозагрузки
Хотел установить kali Linux как 2 ОС на компьютер (disk C). Установил криво. Хотел удалить. Сделал резервное восстановление. Но Linux...

Помагите с Debian Gnu Linux ?
Помагите я установил но дальше тупик какойто что делать в ней не знаю помагите ? хотел проектировать но не знаю как ?

Не работает kali linux на VirtualBox 6.0.16 r135674 (Qt5.6.2)
Сразу же - почему то при создании новой операционки есть только 32 битные варианты всех систем, погуглил. Проблема в отсутствии поддержки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
63
Ответ Создать тему
Опции темы

Новые блоги и статьи
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru