Pull to refresh

Будни DevOps: cобираем gcc 9.3.1 под CentOS 8

Северсталь*nixDevOps

В «Северстали» внедрены большие корпоративные системы, такие как SAP или QMET, но есть и много разных задач, которые закрывает собственная разработка, и задачи у этой разработки редко бывают простыми. А значит, и требования к инструментам разработки бывают достаточно специфическими. Что делать, если вашим разработчикам потребовался gcc-9 под CentOS, а его нет в общедоступных репозиториях? Конечно, засучить рукава и создать требуемые пакеты. Вот только задача эта выглядит просто только на первый взгляд.

Если вам интересно, какие грабли разложены на пути к замене системного компилятора, и как мы с ними справились, добро пожаловать под кат.

Stage 1. Собственно сборка gcc

Здесь казалось бы всё просто: берём gcc.spec от пакета gcc-8.3.1, меняем 8 на 9, запускаем rpmbuild –bb, долго ждём? Да, но нет. Для начала придётся пересмотреть и поправить все патчи, а заодно ещё и поставить binutils посвежее, благо это несложно. Потом, мы же не просто так компилятор меняем, нам же ещё какие-нибудь nvptx-tools подавай, а это значит, что когда сборка закончится и начнется тестирование, тесты в libgomp, завязанные на выгрузку кода, начнут виснуть и застревать в разных странных позах.

Решения тут может быть два:

  1. Консервативное: сказать разработчикам «извините, не шмогла» и отключить nvptx-tools.

  1. Экспериментальное: предупредить разработчиков, что nvptx они используют на свой страх и риск, после чего запустить rpmbuild, дождаться застревания в тестах и отстреливать их руками. Вы получите массовые tests failed в результатах, но искомые пакеты будут собраны.

Stage 2. Package libgcc.i686 has inferior architecture

Итак, мы складываем все эти замечательные gcc-9.3.1-3.el8.x86_64.rpm, gcc-offload-nvptx-9.3.1-3.el8.x86_64.rpm и т.д. и т.п. в отдельный репозиторий, индексируем его, подключаем в /etc/yum.repos.d, говорим dnf update и… Нет, ну вы правда думали, что он возьмёт и сразу поставится? Как бы не так. Как известно, 64-разрядные дистрибутивы семейств Debian и RedHat для семейств процессоров x86 в глубине души немножечко 32-разрядные (то есть, по умолчанию существуют в режиме multilib), и поэтому вам потребуется или объявить multilib пережитком прошлого и снести 32-разрядные библиотеки системного компилятора, или создать соответствующие пакеты (libgcc.i686, libgfortran.i686, libgomp.i686, libquadmath.i686 и libstdc++.i686) для новой версии. Как ни забавно, но решения тут тоже может быть два:

  1. Рекомендованное производителем: поставить mock и выполнить полную сборку для i686, наступив на все сопутствующие грабли (nvptx, например, лучше сразу выключить).

  1. Ленивое на скорую руку: дело в том, что 32-битные версии библиотек на самом деле собираются вместе с 64-битными, но никуда в итоге не попадают. В стандартной версии gcc.spec они вообще тупо удаляются, но это как раз недолго и закомментировать. А потом скопировать gcc.spec в libgcc-i686.spec, вымарать из него всю секцию %build, а в %install написать примерно следующее:

%install 

rm -rf %{buildroot} 

mkdir -p %{buildroot} 

tar cf - -C %{_buildrootdir}/%{name}-%{version}-%{release}.x86_64 usr | tar xf - -C %{buildroot} 

 

FULLPATH=%{buildroot}%{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major} 

FULLEPATH=%{buildroot}%{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_major} 

 

# fix some things 

mkdir -p %{buildroot}/%{_lib} 

mv -f %{buildroot}%{_prefix}/%{_lib}/libgcc_s.so.1 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1 

chmod 755 %{buildroot}/%{_lib}/libgcc_s-%{gcc_major}-%{DATE}.so.1 

ln -sf libgcc_s-%{gcc_major}-%{DATE}.so.1 %{buildroot}/%{_lib}/libgcc_s.so.1 

 

mkdir -p %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib} 

mv -f %{buildroot}%{_prefix}/%{_lib}/libstdc++*gdb.py* \ 

      %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/ 

pushd %{name}-%{version}-%{DATE}/libstdc++-v3/python 

 

for i in `find . -name \*.py`; do 

  touch -r $i %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/$i 

done 

touch -r hook.in %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/libstdc++*gdb.py 

popd 

 

for f in `find %{buildroot}%{_prefix}/share/gcc-%{gcc_major}/python/ \ 

       %{buildroot}%{_datadir}/gdb/auto-load/%{_prefix}/%{_lib}/ -name \*.py`; do 

  r=${f/$RPM_BUILD_ROOT/} 

  %{__python3} -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")' 

  %{__python3} -O -c 'import py_compile; py_compile.compile("'$f'", dfile="'$r'")' 

done 

 

rm -rf %{buildroot}%{_prefix}/%{_lib}/%{name} 

Теперь достаточно сказать rpmbuild –bb libgcc-i686.spec где-то в соседнем терминале, пока gcc развлекается своим torture, и вуаля, наши 32-битные пакеты у нас в кармане (в смысле, в $RPM_BUILD_ROOT/RPMS/i686). Мы копируем их в наш репозиторий, индексируем его, запускаем dnf makecache –repo gcc-9 && dnf update и… Нет, обновить компилятор всё ещё нельзя.

Stage 3. Annobin и libtool

Те, кто внимательно смотрит на параметры сборки на линуксах линеек RHEL и CentOS, могли заметить, что по умолчанию в gcc подключен плагин annobin. У этого плагина есть неприятная привычка привязываться к версии компилятора, поэтому его придется пересобрать. Детали в принципе изложены в самом annobin.spec в комментариях, поэтому отметим только, что пересобрать его придётся минимум дважды: сперва, используя ещё системный gcc 8.3.1, поправить требование к версии gcc, чтобы gcc < %{gcc_next} превратилось в gcc <= %{gcc_next}, потом, уже заменив gcc, пересобрать заново, вернув требование gcc < %{gcc_next} и раскомментировав строку %undefine _annotated_build – иначе вообще ничего собираться не будет. Ну и для чистоты можно пересобрать в третий раз, вернув _annotated_build на место, а предыдущие две версии пакетов (переходную и без аннотации бинарей) из репозитория удалить.

Остается libtool. Этот джентльмен тоже жёстко привязывается к версии gcc, но к счастью, зависимость эта односторонняя, поэтому libtool можно просто удалить перед заменой gcc, затем собрать его заново новым gcc и добавить соответствующий пакет в наш репозиторий gcc-9.

Как ни странно, на этом всё. У нас есть отдельный репозиторий, подключив который, можно поставить требуемую версию компилятора, а при необходимости вернуть обратно системную версию (командой dnf downgrade gcc), хотя необходимости такой у нас не возникало.

Хабравчане-девопсы, а какие у вас бывали нестандартные запросы от разработчиков?

Tags:severstalitpeopledevopslinuxredhatcentosgccrpmbuild
Hubs: Северсталь *nix DevOps
Total votes 10: ↑7 and ↓3 +4
Views1.9K

Information

Founded
Location
Россия
Website
www.severstal.com
Employees
1,001–5,000 employees
Registered