Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

Qt

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 183, средняя оценка - 4.78
gromo
371 / 270 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
#1

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

23.01.2014, 19:10. Просмотров 31635. Ответов 59
Метки нет (Все метки)

В связи с отсутствием в данной теме мануала по статической линковке приложений 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
Код
Объяснение опций:
-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. Добавляем туда
Код
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/ (в данном случае):
Код
LIBS += -Wl,-rpath lib/
Теперь все это дело в .tar.gz и можете делиться с друзьями своим приложением

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

Ps. На MacOS процедура практически не должна отличаться, но у меня нет возможности проверить.
Pss. Если ваше приложени базируется на плагинах, то они по своей природе не могут линковаться статически..
Смотрите документацию http://qt-project.org/doc/qt-4.8/deployment-x11.html и все вытекающие перекрестные ссылки по плагинам.
___________________________________________________________________________________________________________
Вроди бы ничего не забыл...
Надеюсь, статейка кому-нибудь поможет разобраться.
Спасибо и удачи
5
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.01.2014, 19:10
Здравствуйте! Я подобрал для вас темы с ответами на вопрос GNU/Linux Qt5.* - Линкуем статически (C++ Qt):

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

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

Как статически ликовать QT 5.3.0 - C++ Qt
Как статистически ликовать QT 5.3.0 Собирать утилиты без требований библиотек QT да видел варианты QT 4.7 и другие - но по их...

Как собирать программу статически? - C++ Qt
Как собирать программу статически? Скиньте ссылку на нормальный мануал.

qmake. Заставить GCC линковать статически - C++ Qt
Нужно слинковать библиотеку GMP статически. Такая вещь в .pro файле, естественно, предпочитает динамические либы: unix:LIBS +=...

Задать количество строк и столбцов статически. QGridLayout - C++ Qt
Здравствуйте. опять прошу, подскажите метод или алгоритм: обычно менеджер компоновки QGridLayout занимает весь родительский виджет, и...

59
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 15:00 #31
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Может где-то в Qt Creator надо настройки изменить?
Он тут вообще не при чем.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 15:04 #32
А как тогда исправить? Отличия от инструкции заключались только в том, что пришлось использовать команду sudo, без нее выскакивали ошибки еще на стадии ./configure.
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 15:16 #33
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
что пришлось использовать команду sudo
Она не нужна. Вы что-то делали не так.

Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Отличия от инструкции
какой инструкции?
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 15:21 #34
Инструкция из этой темы, первое сообщение. Я уже описывал проблему ранее:

Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Никак не получается собрать библиотеки. Выскакивает ошибка:

Код
Running configuration tests...
The test for linking against libxcb and support libraries failed!
*You might need to install dependency packages, or pass -qt-xcb.
*See src/plugins/platforms/xcb/README.
Пробовал добавлять ключ -qt-xcb, выдало:

Код
NOTE: libxkbcommon and libxkbcommon-x11 0.4.1 or higher not found on the system, will use 
the bundled version from 3rd party directory.
Could not find qmake configuration file linux-g++.
Error processing project file: /home/oleg/Загрузки/qt-everywhere-opensource-src-5.3.2/qt.pro
Без sudo она не собирается. Сделать что-то НЕ так я точно не мог, скачал, распаковал в папку через терминал, запустил команду ./configure со всеми флагами из инструкции, запустил make / make install. Ошибиться там невозможно.
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 15:42 #35
KOSHAK_, если у вас кубунта, то нужно зависимости сборки установить как в примерах выше:
Bash
1
sudo apt-get install build-essential ^libxcb.* libx11-xcb-dev libglu1-mesa-dev libxrender-dev libfontconfig1-dev
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Сделать что-то НЕ так я точно не мог
Ну раз у вас не работает - значит могли. Сборка Qt из сорцов не самая тривиальная задача.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 16:26 #36
Так там всего 3 команды...
Собрал библиотеки под виртуалкой,но на kUbuntu x64. Перекинул бинарник в Astra Linux, запускаю, а он мне:

Код
st: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by ./Test)
./Test: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.15' not found (required by ./Test)
./Test: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by ./Test)
Вот с этим уже вообще непонятно что делать. Astra невероятно убогая шняга, основан на Debian, в нем даже все репозитории удалены. Где можно эти библиотеки скачать и как обновить?
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 16:33 #37
KOSHAK_, это уже совсем другая проблема. При сборке в статику нужно использовать более старые системные библиотеки чем на запускаемой машине.
То есть если вы собрали Qt на Ubuntu 14.04, то он не будет работать на 12.04, а на оборот будет. То есть вы должны собрать/слинковать Qt с либами старее чем у вас в ошибках.

Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Так там всего 3 команды...
За этими командами кроется очень много магии.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 16:38 #38
А можно подробнее про старые библиотеки? Как мне с ними собрать? В принципе вся задача в том, чтобы приложение запустилось на этой убогой системе, но писать что-то в ней не вариант, опять же из-за ее убогости и древности...
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 16:41 #39
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Как мне с ними собрать?
Собрать кьют в древней системе. К примеру в Ubuntu 10.04 GLIBC_2.11. Вот на ней можете и собрать.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 16:44 #40
Ага, т.е. поставить на виртуалку древнюю систему и собирать в ней? А версию Qt можно оставить прежней?
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
14.01.2015, 16:52 #41
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
А версию Qt можно оставить прежней?
Да. Скорее всего проблем не будет.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
14.01.2015, 16:54 #42
Спасибо, пошел качать образ. В пятницу продолжу мучения
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
16.01.2015, 17:05 #43
Блин, на старой Ubuntu Qt Creator 1.3.1. он отказывается работать с Qt 5.3.2. Можно поставить туда новый Qt Creator?
0
RazrFalcon
1380 / 1237 / 262
Регистрация: 10.11.2013
Сообщений: 3,763
16.01.2015, 17:14 #44
Цитата Сообщение от KOSHAK_ Посмотреть сообщение
Можно поставить туда новый Qt Creator?
Да. А зачем он вам вообще? Qt собирается через консоль на раз-два.
0
KOSHAK_
1 / 1 / 0
Регистрация: 16.11.2011
Сообщений: 108
16.01.2015, 17:24 #45
А GUI создаваемой программы? Или можно взять проект из нового Qt Creator и просто пересобрать его в старом линуксе через консоль?
0
16.01.2015, 17:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.01.2015, 17:24
Привет! Вот еще темы с ответами:

Учебник по qt5 - C++ Qt
Я знаю, что этот вопрос много раз задавался, но везде под 4 версию, а там, где просят учебники под 5, нет ответа пожалуйста, посоветуйте...

Qt5 + Raspberry Pi - C++ Qt
Кто-нибудь может подсказать и описать, каким образом я могу собрать сам Qt5 под Raspberry Pi (кросс-компиляцией какой-нибудь, чтобы этот...

QT5/0/1 библиотеки - C++ Qt
есть код, есть хекс и длл файл и исходники, нет библиотек. кто сможет помочь? уже 5 сутки долбаюсь. вот само задание &quot;Задача о...

Qt5 Vk API - C++ Qt
Всем привет. Решил поиграться с vk api. Возник не большой трабл. Имеем три файла #include &lt;QObject&gt; #include &lt;QWidget&gt; #include...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru