Добрый день друзья. Как-то мне захотелось установить Qbittorrent на мой роутер который оснащен OpenWRT. Конечно создатели OpenWRT уже предусмотрели возможность сборки кастомных пакетов об этом можно почитать вот тут: https://habr.com/ru/company/ruvds/blog/530984/ . Но данный способ очень долгий, приходится скачивать исходники OpenWRT, компилировать тулчейн и прочее. И я подумал, а почему-бы просто не скачать тулчейн и собрать проект обычным образом. Под катом мой опыт.

Тулчейны что это такое

Итак, для людей которые недавно познакомились с Linux (как впрочем и я) поясняю тулчейн это набор пакетов необходимый для сборки приложения. В него входят компилятор, линкер и т. д, программой которая вызывает всю цепочку пакетов называется gcc. Для Linux существует множество тулчейнов которые позволяют собирать программы как под другие операционные системы (Windows и т. д) так и под другие платформы (Arm и т. д). Например тулчейн для Windows называется MinGW. При помощи него можно компилировать программы для Windows прямо из под Linux звучит как магия.

Подготовка

Что нам нужно? Нам нужен Linux все опыты проводились в Linux Mint. На него нужно установить следующие пакеты:

sudo apt update
sudo apt install build-essential curl pkg-config automake libtool \
git perl python3 python3-dev python3-numpy \
unzip cmake ninja

Также нам нужен тулчейн. Какие бывают тулчейны? Ну во первых они отличаются архитектурой под которую они собирают пакеты. Также они могут иметь разные стандартные библиотеки языка C. Наиболее распространённая библиотека это glibc, но нам она не подойдет, поскольку OpenWRT использует библиотеку musl. Поэтому заходим по ссылке https://musl.cc/#binaries и качаем нужный тулчейн. Поскольку мой роутер использует процессор с архитектурой aarch64, то я выберу aarch64-linux-musl-cross и скачаю его. Распаковываем его в папку, путь к которой далее я буду называть crosshost_dir для краткости.

Также нам необходимы исходники не только Qbittorrent, но и исходники всех библиотек которые используются в Qbittorrent.

  1. zlib https://github.com/madler/zlib

  2. openssl https://github.com/openssl/openssl Нужна версия с l (OpenSSL_1_1_1l)

  3. boost https://boostorg.jfrog.io/ui/native/main/release/1.77.0/source

  4. libtorrent https://github.com/arvidn/libtorrent Версию 2 поддерживает только qbittorrent 4.4

  5. qt-everywhere https://download.qt.io/archive/qt/5.15/5.15.2/single/

  6. qbittorrent https://github.com/qbittorrent/qBittorrent

Также нужно создать папку в которой мы будем работать и распаковать в неё все эти архивы. Эту папку я далее буду называть Install_dir. В ней нужно создать папку Build в которую будут складываться результаты наших трудов.

Теория

Во первых хочется предупредить об одной вещи. Если внутри параметра который вы передаёте в консоль присутствует пробел, то этот параметр обязательно должен быть помещен в кавычки. Иначе система посчитает что вы передаете ей два параметра.

Существует два типа связывания библиотек это статический и динамический. При статическом связывании код библиотеки помещается внутрь программы. При динамическом линкер создаст специальный раздел программы называемый таблицей импорта. При старте программы, загрузчик читает эту таблицу импорта и подгружает библиотеки из внешних файлов которые имеют расширение .so .

К сожалению если мы применим динамическое связывание наша программа не запустится. Система будет жаловаться на неопределённые символы. Поэтому мы применим статическое. Одним из плюсов данного подхода будет то, что у нас будет самая актуальная версия библиотек. А это очень важно например в случае с Libtorrent эта библиотека очень быстро обновляется и сильно влияет на работу Qbittorrent. Но отрицательной стороной данного подхода является сильно разросшийся размер программы. Например у меня получился Qbittorrent размером 22 МБ . Кажется это немного, но нужно помнить что ещё недавно у роутеров было 4 МБ флэш памяти и 4 МБ оперативной памяти.

Сборка любого проекта состоит из 3-х этапов

  1. Конфигурирование

  2. Сборка

  3. Инсталляция пакета. То есть перенос его в нужную директорию.

В Linux существует две системы сборки проектов это Autotools и Сmake. Autotools это устаревшая система но некоторые проекты до сих пор используют её. Поэтому мы будем использовать и ту и другую.

Сборка

Перед началом сборки нужно добавить несколько переменных окружения которые скажут системе где расположен наш проект и наш тулчейн, а также под какую платформу мы будем компилировать. Для тех кто не знает, все значения переменных окружения хранятся лишь до тех пор пока вы не закрыли терминал. То есть закрыли открыли терминал вводите переменные заново.

PATH=crosshost_dir/bin:$PATH
PATH=Install_dir/Build/bin:$PATH

CHOST=aarch64-linux-musl
CC=aarch64-linux-musl-gcc
AR=aarch64-linux-musl-ar
CXX=aarch64-linux-musl-g++
PKG_CONFIG_PATH="Install_dir/Build/lib/pkgconfig"
LD_LIBRARY_PATH=-L"Install_dir/Build/lib"

BOOST_ROOT="Install_dir/Build/boost"
BOOST_INCLUDEDIR="Install_dir/Build/boost"
BOOST_BUILD_PATH="Install_dir/Build/boost"

aarch64-linux-musl надо заменить на тот тулчейн который вы скачали.

Zlib

./configure --prefix=Install_dir/Build --static 
make -j8 CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar \
CXX=aarch64-linux-musl-g++ \
CXXFLAGS="-std=c++17 -static -w -s -IInstall_dir/Build/include" \
CPPFLAGS="-static -w -s -IInstall_dir/Build/include" \
LDFLAGS="-static -Wl,--no-as-needed -LInstall_dir/Build/lib -lpthread -pthread"
make install

После -j нужно поставить количество ядер вашего процессора у меня их 8. Zlib упорно не хотел воспринимать переменные среды поэтому пришлось передать их вместе с командой make.

OpenSSl

./Configure "linux-aarch64" --prefix=Install_dir/Build \
--openssldir="/etc/ssl" threads no-shared no-dso no-comp
make -j8 CC=aarch64-linux-musl-gcc AR=aarch64-linux-musl-ar \
CXX=aarch64-linux-musl-g++ \
CXXFLAGS="-std=c++17 -static -w -s -IInstall_dir/Build/include" \
CPPFLAGS="-static -w -s -IInstall_dir/Build/include" \
LDFLAGS="-static -Wl,--no-as-needed -LInstall_dir/Build/lib -lpthread -pthread"
make install_sw

Тут все похоже на прошлый.

Boost

Boost устанавливать не надо. Нужно просто переместить его в папку Install_dir/Build. И переименовать его папку просто в boost. А проекты которые от него зависят сами возьмут из этой папки что им надо.

Libtorrent

mkdir -p Install_dir/Build/graphs/libtorrent-rasterbar
patch -p1 < patch-libtorrent
cmake -Wno-dev -Wno-deprecated \
--graphviz=Install_dir/Build/graphs/libtorrent-rasterbar/dep-graph.dot \
-G Ninja -B build -DCMAKE_CXX_COMPILER=aarch64-linux-musl-g++ \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 \
-DCMAKE_PREFIX_PATH="Install_dir/Build;Install_dir/Build/boost" \
-DBoost_NO_BOOST_CMAKE=TRUE \
-DCMAKE_CXX_FLAGS="-std=c++17 -static -w -s -IInstall_dir/Build/include" \
-DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX="Install_dir/Build"
cmake --build build
cmake --install build

Для того чтобы собрать Libtorrent нужно применить патч . Здесь уже используется cmake.

Qt

Надо отметить что Qbittorrent до сих пор не поддерживает Qt 6-й версии поэтому нужно брать пятую. Перед сборкой нужно зайти в файл qt-everywhere_dir/qtbase/mkspecs/linux-aarch64-gnu-g++/qmake.conf и заменить aarch64-linux-gnu на aarch64-linux-musl или на вашу архитектуру если у вас другой тулчейн.

./configure -xplatform "linux-aarch64-gnu-g++" -prefix "Install_dir/Build" \
-no-icu -no-iconv  -opensource -confirm-license -release  -static -c++std "c++17" \
-qt-pcre -no-feature-glib -no-feature-opengl -no-feature-dbus -no-feature-gui \
-no-feature-widgets -no-feature-testlib -no-compile-examples -nomake examples \
-nomake tests -no-opengl -skip 3d -skip activeqt -skip androidextras \
-skip datavis3d -skip doc -skip macextras -skip quick3d -skip quickcontrols \
-skip quicktimeline -skip translations -skip wayland -skip webengine \
-skip webglplugin -skip winextras -skip x11extras  -I"Install_dir/Build/include" \
-L"Install_dir/Build/lib" \
QMAKE_LFLAGS="-static -Wl,--no-as-needed -LInstall_dir/Build/lib -lpthread -pthread"
make -j8
make install

Qbittorrent

mkdir -p Install_dir/Build/graphs/qBittorrent-release-4.4.0beta3
cmake -Wno-dev -Wno-deprecated \
--graphviz="Install_dir/Build/graphs/qBittorrent-release-4.4.0beta3/dep-graph.dot" \
-G Ninja -B build -DCMAKE_CXX_COMPILER="aarch64-linux-musl-g++" \
-DCMAKE_BUILD_TYPE="release" -DCMAKE_CXX_STANDARD="17" \
-DCMAKE_PREFIX_PATH="Install_dir/Build;Install_dir/Build/boost" \
-DBoost_NO_BOOST_CMAKE=TRUE \
-DCMAKE_CXX_FLAGS="-std=c++17 -static -w -s -I"Install_dir/Build/include"" \
-DSTACKTRACE=OFF -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DGUI=OFF \
-DCMAKE_INSTALL_PREFIX="Install_dir/Build"
cmake --build build
cmake --install build

Настройка и запуск Qbittorrent

Первым делом нужно переместить файл qbittorrent-nox в директорию \usr\bin вашего роутера. Теперь можно попробовать его запустить с опцией -d чтобы он запустился в режиме демона, иначе он выключится как только вы закроете окно putty. Но во первых делать это каждый раз неудобно да и qbittorrent запускается с правами root а это небезопасно. Поэтому сначала добавляем пользователя qbittorrent:

echo qbittorrent:x:227:227:qbittorrent:/home/qbittorrent:/bin/false >> /etc/passwd
echo qbittorrent:x:227:qbittorrent >> /etc/group
echo qbittorrent:x:0:0:99999:7::: >> /etc/shadow

После этого создаете файл /etc/init.d/qbittorrent

#! /bin/sh /etc/rc.common
USE_PROCD=1

START=98
STOP=01

DAEMON="/usr/bin/qbittorrent-nox"
USER="qbittorrent"
GROUP="qbittorrent"
home_dir="/home/qbittorrent"

start_service() {

	[ -d "$home_dir" ] || {
		mkdir -p "$home_dir"
		chmod 0755 "$home_dir"
		chown "$USER:$GROUP" "$home_dir"
	}

	procd_open_instance
	procd_set_param command "$DAEMON"
	procd_set_param user $USER
	procd_set_param group $GROUP
	procd_set_param env HOME="$home_dir"
	procd_close_instance
}

И разрешаете выполнение:

chmod 755 /etc/init.d/qbittorrent

Теперь qbittorrent'ом можно управлять как и другими демонами из веб интерфейса.

Где можно взять Qbittorrent если не хочется компилировать?

Конечно-же все это я взял не с потолка. На github я нашел репозитарий https://github.com/userdocs/qbittorrent-nox-static там есть скрипт который все вышесказанное сделает за вас. Но кроме того в разделе релизов уже лежат скомпилированные Qbittorrent'ы нужно только выбрать подходящую архитектуру процессора.

Комментарии (14)


  1. ner0
    19.09.2021 11:56
    -1

    Чем qBittorrent лучше других аналогичных программ?


    1. qark
      19.09.2021 13:06

      Холивар?


    1. deema35 Автор
      19.09.2021 14:38
      +3

      Исходники открыты, поэтому его можно запустить даже на утюге. И он по возможностям не уступает utorrent. Что нужно ещё.


      1. gudvinr
        19.09.2021 18:47
        -1

        А по сравнению с deluge, transmission и rtorrent?


        1. gudvinr
          20.09.2021 12:36
          +1

          Интересно конечно. Минус поставили, но так и не ответили.


          • Собранный qbt в 2 раза больше места занимает, чем rtorrent (вместе с libtorrent) или transmission
          • Для qbt нужен Qt даже для nox версии. Да, только qt base, но и он много места занимает. В несколько раз больше самого qbt.
            Из внешних зависимостей у transmission — libevent и у rtorrent — xmlrpc.
          • libtorrent-rasterbar собирается с boost. Да, он не весь буст использует наверняка, но это тоже немаленькая библиотека. При этом собранный libtorrent-rasterbar требует больше места, чем сам qbt.
            Вместе с тем, rtorrent и transmission используют свои собственные реализации и по большому счёту зависят только от curl.

          transmission и rtorrent с зависимостями занимают не больше 6Мб. 22Мб — это не немного. Это безумие — устанавливать на роутеры приложения, которые занимают больше 20Мб.


          Deluge, т.к. использует Python, будет требовательнее к месту и ресурсам. Но и у него исходники тоже открыты


          1. deema35 Автор
            20.09.2021 15:04

            Я пользовался Transmission и у неё имеются серьёзные проблемы с поиском пиров. Почитать об этом можно здесь https://github.com/transmission/transmission/issues/1036 я конечно не знаю остались ли эти проблемы до сих пор но год назад все было как там написано. Собственно из-за этого я перешел на Qbittorrent.


  1. abagnale
    19.09.2021 13:06

    sudo apt install ninja

    Если правильно помню, такого пакета не найдёт, надо ставить ninja-build.

    sudo apt install curl

    А этот, вроде бы, поставит только утилиту cURL, но не библиотеки, возможно надо ставить libcurl4-openssl-dev.


  1. ivanstor
    19.09.2021 14:34
    +3

    С великая могучая русская языка у автора явно напряженка. Склонениев, спряжением, согласованием и пунктуацией не даётся.
    Я не граммар-наци, но глаз режет. С содержанием тоже не всё хорошо.

    Хабр всё больше превращается в помесь пикабу и полного собрания пресс-релизов. Про прокладки, правда, пока ничего нет — это не может не радовать.


    1. bazilxp
      19.09.2021 20:47
      +1

      Да с содержимым сложно, toolchain специфичен под прошивку .

      Ну мысль автор нес , почти донес ....


  1. unsignedchar
    20.09.2021 12:48

    Если брать исходники библиотек тех же версий, что уже установлены в роутере — можно использовать динамическую линковку и обходиться без бинарников в 20 Мб.


  1. deema35 Автор
    20.09.2021 15:18

    Придется долго подбирать. Особенно учитывая что библиотеки libc и libstdcpp мы наследуем из тулчайна. То есть нам придется ещё и версию тулчайна подбирать.


    1. unsignedchar
      20.09.2021 16:00

      Придется долго подбирать.


      Зная номер версии OpenWRT — недолго.


      1. deema35 Автор
        20.09.2021 16:13

        Ну в смысле что тогда проще скачать исходники OpenWRT и там уже будут необходимые версии библиотек и тулчайн.


  1. AlexGluck
    20.09.2021 19:22
    +1

    Вот оформить бы содержимое статьи в докерфайл и кросскомпиляцией собрать, вроде как даже встречал на гитхабе шаблоны для сборки в докере и подман.