Search
Write a publication
Pull to refresh

Собираем C++20 код под Ubuntu 16.04

Level of difficultyMedium

Для начала поведаю, зачем это нужно Тут всё банально. Пишу небольшой проект (есть у меня на гитхабе, ссылку дам в конце), который может работать как под windows, так и в линуксе. Когда пришла пора испытывать его в «боевых» условиях, решил поставить его к себе на VPS (минимальная конфигурация, но для моих нужд вполне достаточна). Эту VPS я арендую уже много лет и крутится там та самая 16.04. Много лет и без апгрейдов. А зачем? Работает и хорошо. Заливаю свежесобранный exe'шник (или как там у линуксоидов оно называется), который собирался в убунте 22.04 при помощи gcc 15, и, ожидаемо получаю ошибку типа: version `GLIBC_2.35' not found. Всё, приехали. Предварительные танцы с бубном ничего не дали. Систему я обновить не могу (тариф VPS это не позволяет), gcc 10 (минимальный для сборки c++20) там уже нет. Опыта в линуксах у меня никакого. Что делать?

Самое простое решение, которое удалось нагуглить и напромптить — прилинковать все библиотеки статически, указав ‑static в опциях компилятора. И это чудесным образом заработало, увеличив исполняемый файл в два раза.

На этом можно было бы и остановиться, но меня смущали ворнинги, утверждающие, что работать оно будет плохо (ругалось на некоторые системные вызовы). И вообще статическая линковка библиотек — это вообще не linux way. Поэтому я решил все таки попробовать пойти по более сложному пути, а именно обновить gcc и собрать всё на месте. О чем и пойдет речь далее.

Первым делом выяснилось, что последняя версия gcc, которую можно легко поставить в столь древней убунте — это gcc 9. Что‑ж, с нее и начнем:

sudo apt install gcc-9
# добавим ее в систему выбора альтернатив. Это сделает gcc-9 активным по умолчанию
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 90

Более новые версии в готовом виде найти не удалось, поэтому остался единственный путь: собирать gcc 11 прямо из исходников. Не знаю почему 11 а не 15. Наверное, решил не рисковать и начать с малого, впрочем кто‑то может начать сразу с 15-й, но я не гарантирую результат, т.к. не пробовал, а точнее я таки поставил 15-ю, но уже после 11-й. Вопреки ожиданиям (я windows‑программист и для меня мир линукса — страшная тёмная комната), сей процесс оказался не таким уж сложным. Были мелкие камешки, о которые я спотыкался по неопытности, но в целом всё получилось. Ах да, сначала надо обновить/установить разные непонятные штуки. С трудом понимаю их смысл, но все руководства наперебой советуют это сделать, значит будем делать:

sudo apt install build-essential libgmp-dev libmpfr-dev libmpc-dev texinfo

далее серия команд с комментариями, что и зачем:

# заходим в домашнюю папку (корее всего вы уже там)
cd ~
# скачиваем исходники 11-й версии gcc
wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.xz
# распаковываем
tar -xf gcc-11.2.0.tar.xz
# теперь у нас есть папка gcc-11.2.0. зайдем в нее и скачаем необходимые зависимости
cd gcc-11.2.0
./contrib/download_prerequisites
# всё, покидаем эту папку, в ней нам больше делать нечего (важно! сборка должна проходить в другой папке)
# создаем отдельную папку для сборки:
cd ..
mkdir gcc11
cd gcc11
# мы внутри gcc11, конфигурируем:
../gcc-11.2.0/configure --enable-languages=c,c++ --disable-multilib --disable-bootstrap --disable-selftest --enable-lto --prefix=/opt/gcc-11
# пояснение к параметрам конфигурации:
# --enable-languages=c,c++ - будем собирать только c и c++
# --disable-multilib - оставляем только сборку под текущую архитектуру, остальные долой
# --disable-bootstrap --disable-selftest - ускоряем сборку, выкидывая из нее тесты
# --enable-lto - возможно оно включено и так, но лучше включить явно. Очень полезная штука - Link Time Optimization
# --prefix=/opt/gcc-11 - самая главная опция - путь, куда после сборки gcc будет установлен
# без этой опции мы не сможем переключаться между версиями gcc и вообще будут проблемы
# далее запускаем сборку (если у вас 4 ядра то укажите ключ -j4, чтобы собиралось быстрее)
make
# ждем

Сборка пошла. Можете пойти выпить кофе. Минимум 10 минут у вас есть. По окончании сборки, устанавливаем свежесобранный gcc:

sudo make install

Ура! Мы получили gcc 11 в нашей древней системе. Половина квеста пройдена. Сейчас надо добавить этот gcc в систему в качестве альтернативы, чтобы в будущем иметь возможность переключаться между версиями.

sudo update-alternatives --install /usr/bin/gcc gcc /opt/gcc-11/bin/gcc 110
sudo update-alternatives --install /usr/bin/g++ g++ /opt/gcc-11/bin/g++ 110

Для переключения надо будет выполнять:

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

Компилятор‑то мы обновили. А вот сборщик — нет. Всякие новомодные инструкции, типа avx2, если таковые будут в вашем коде, не дадут exe‑шнику собраться. В моём проекте они были — именно так я узнал, что gcc — это только компилятор. Есть еще binutils — утилиты сборки. Ну что‑ж, будем обновлять binutils:

# качаем и распаковываем последнюю версию на момент написания этой статьи
wget https://ftp.gnu.org/gnu/binutils/binutils-2.44.tar.gz
tar -xf binutils-2.44.tar.gz
# также создаем отдельную папку для сборки
mkdir bu244
cd bu244
# конфигурируем и запускаем сборку
../binutils-2.44/configure --prefix=/opt/binutils244
make # или make -jN, где N - количество ядер - для ускорения сборки
# устанавливаем
sudo make install

Почти всё. теперь, чтобы собрать ваш проект, нужно заставить gcc использовать свежие binutils. Самый простой способ — добавить новые binutils в путь перед сборкой:

export PATH=/opt/binutils242/bin:$PATH # этот путь был указан при конфигурировании
make # это сборка вашего проекта, если что

Проверить, что будет использована свежая версия binutils можно так:

ld --version

Я у себя решил пойти дальше и проделал все эти шаги для установки более свежей версии gcc-15. Все получилось. Я не знаю, получилось бы у меня собрать 15-ю версию gcc с помощью 9-й, не проверял. Но 11-я справилась прекрасно.

Вот теперь точно всё. Код c++20 прекрасно собрался и заработал на старенькой Ubuntu 16.04. То что надо.

ссылка на проект, как обещал

Не хочу тут описывать, что за проект. Статья, не о нем все-таки. Скажу только - это 3proxy на максималках. Кто знает, тот знает.

https://github.com/oxygene-user/proxtopus

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.