Часть программ стали требовать поддержку стандарта C++17 и в компиляторе, и в стандартной библиотеке C++.
В Росе давно был и есть компилятор clang достаточно свежей версии, поддерживающий C++17, но в системной libstdc++ от GCC 5 нет поддержки C++17. Из-за этого не получалось собрать, например, LibreOffice 6.3.
Есть несколько возможных решений проблемы:
1) Использовать libc++ от LLVM вместо libstdc++
Реализовать это невозможно из-за несовместимых ABI libc++ и libstdc++.
Невозможно слинковать бинарник, собранный с libc++, с другой библиотекой, слинкованной с libstdc++, а если и слинкуется, запускать такое опасно — упадет.
2) Подход в стиле BSD-систем, в т.ч. DragonFlyBSD, использующей GCC в качестве основного компилятора:
собрать новую версию компилятора gcc в отдельный префикс вместо стандартного /usr, а при сборке программ ставить RUNPATH на папку с библиотеками этого gcc вне стандартных директорий. Тогда при запуске собранной так программы будет использоваться libstdc++.so.6 из той папке вместо общесистемной.
Плюсы:
+ простота сборки и использования нового компилятора
+ новый компилятор сам найдет заголовочные файлы новой libstdc++
Минусы:
- т.к. новая libstdc++.so.6 будет лежать в особой папке, где ее будут искать только те программы, у которых стоит специальный RUNPATH, нужно отключить AutoProv в RPM-пакете с новой libstdc++, а в собранных с ней пакетах вручную прописывать зависимости вместо того, чтоб машина, не завися от человеческого фактора, сама их прописала
3) Собрать что-то вроде Red Hat Compiler Collection
libstdc++.so.6 вообще не собирать, собрать только статическую libstdc++.a и при этом оставить в ней только те символы, которых нет в общесистемной libstdc++.so.6, а затем линковать ее статически
Это очень сложно и требует очень много времени
4) [ что было сделано ]
Собрать gcc актуальной версии, убрать все лишнее, оставить только libgcc_s.so.1, libstdc++.so.6 и заголовочные файлы
libstdc++.so.6 переименовать в libstdc++-gcc10.so.6 (и файл переименовать, и soname библиотеки изменить)
Аналогично переименовать libgcc_s.so.1 в libgcc_s-gcc10.so.1
Поменять у libstdc++-gcc10.so.6 зависимость от libgcc_s.so.1 на зависимость от libgcc_s-gcc10.so.1
Переместить заголовочные файлы в отдельную папку
Упаковать это все в пакет: https://abf.io/import/libstdc++-gcc10/tree/rosa2016.1
На примере пакета LibreOffice 6.3 разберем, как это использовать.
В BuildRequires нужно добавить "stdc++-gcc10" и компилятор clang:
Код: Выделить всё
BuildRequires: clang
BuildRequires: stdc++-gcc10-devel
Во флагах компилятора нужно:
- добавить "-nostdinc++", чтобы компилятор не брал заголовочные файлы от системной libstdc++
- указать путь к правильным заголовочным файлам: "-I/usr/include/libstdc++-gcc10 -I/usr/include/libstdc++-gcc10/%{_host}"
- добавить "-lstdc++-gcc10" во флаги линковщика
В LibreOffice еще понадобилось сделать скрипт-обертку, который принимал на вход команду для компилятора, но переставлял флаги так, чтобы все флаги -lxxx шли в конце.
В результате бинарники слинкованы одновременно с libstc++-gcc10.so.6 и libstdc++.so.6. В теории может возникнуть несовместимость, например, при использовании конструкторов копирования в C++, когда как объекты в libstdcc++-gcc10.so.6 и libstdc++.so.6 могут отличаться, а со старой libstdc++.so.6 собраны другие библиотеки, используемыми LibreOffice'ом, но на практике не удалось найти проблем и вызвать падений.