Проект C++, скомпилированный современным компилятором, но связанный с устаревшей libstdc++

avatar
Vitaly Isaev
2 октября 2018 в 13:22
1732
1
9

Рассмотрите ситуацию, когда проект C++ создается и поставляется внутри Centos 7 виртуальной машины или контейнера. По умолчанию gcc вместо Centos 7 равно 4.8. Чтобы позволить разработчикам использовать современный C++, более поздняя версия gcc (например, 6.3) устанавливается в Centos 7, который работает как сервер CI. Это обеспечивает поддержку -std=c++14.

[builder@f7279ae9f33f build (master %)]$ /usr/bin/c++ -v 2>&1 | grep version
gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
[builder@f7279ae9f33f build (master %)]$ /opt/rh/devtoolset-6/root/usr/bin/c++  -v 2>&1 | grep version
gcc version 6.3.1 20170216 (Red Hat 6.3.1-3) (GCC) 
export CXX=/opt/rh/devtoolset-6/root/usr/bin/c++
make all -j4
...

Это краткий пример команды компиляции и компоновки:

[ 78%] Building CXX object CMakeFiles/ucsdos.dir/src/merge_operator_string.cpp.o
/opt/rh/devtoolset-6/root/usr/bin/c++  -Ducsdos_EXPORTS -I/home/builder/src/dos/libucsdos/./src -I/home/builder/src/dos/libucsdos/./include -I/home/builder/src/dos/libucsdos/build/schema/cpp -I/home/builder/src/dos/libucsdos/build/schema -isystem /usr/local/include  -O2 -g -DNDEBUG -fPIC   -frtti -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused -std=gnu++14 -o CMakeFiles/ucsdos.dir/src/merge_operator_string.cpp.o -c /home/builder/src/dos/libucsdos/src/merge_operator_string.cpp

[ 80%] Linking CXX shared library libucsdos.so
/usr/bin/cmake3 -E cmake_link_script CMakeFiles/ucsdos.dir/link.txt --verbose=1
/opt/rh/devtoolset-6/root/usr/bin/c++ -fPIC -O2 -g -DNDEBUG  -shared -Wl,-soname,libucsdos.so.0 -o libucsdos.so.0.3.23 CMakeFiles/ucsdos.dir/src/c.cpp.o CMakeFiles/ucsdos.dir/src/crdt_2p_set.cpp.o CMakeFiles/ucsdos.dir/src/crdt_pn_counter.cpp.o CMakeFiles/ucsdos.dir/src/errors.cpp.o CMakeFiles/ucsdos.dir/src/merge_index_document.cpp.o CMakeFiles/ucsdos.dir/src/merge_index_segment.cpp.o CMakeFiles/ucsdos.dir/src/merge_operator_string.cpp.o -Wl,-rpath,/usr/local/lib: schema/libschema.a /usr/lib64/librocksdb.so /usr/lib64/libjemalloc.so /usr/local/lib/libgrpc++_reflection.so /usr/local/lib/libgrpc++.so /usr/local/lib/libgrpc.so -ldl -lgrpc++ /usr/lib64/libprotobuf.so -lpthread /usr/lib64/libprotobuf-lite.so 

В любом случае, полученные артефакты связаны с версией системы по умолчанию libstdc++:

[builder@f7279ae9f33f build (master %)]$ ldd libucsdos.so | grep libstdc++.so.6
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f2a4a054000)

Легко узнать, что /lib64/libstdc++.so.6 версия 4.8.5:

[builder@f7279ae9f33f build (master %)]$ yum whatprovides "/lib64/libstdc++.so.6"
libstdc++-4.8.5-28.el7_5.1.x86_64 : GNU Standard C++ Library
Repo        : @Updates
Matched from:
Filename    : /lib64/libstdc++.so.6

Действительна ли эта конфигурация среды сборки?

Источник
Fire Lancer
2 октября 2018 в 13:30
1

Используете ли вы заголовки для старого libstdС++ или для нового?

Vitaly Isaev
2 октября 2018 в 13:55
1

@FireLancer Я не включаю заголовки libstdc++, я думал, что компилятор должен делать это неявно (обновил вопрос).

Marc Glisse
2 октября 2018 в 14:26
1

Похоже на вариант gcc.gnu.org/faq.html#rpath

Ответы (1)

avatar
Jonathan Wakely
2 октября 2018 в 15:04
13

В любом случае, полученные артефакты, похоже, связаны с системной версией libstdc++ по умолчанию:

Да. Пакет devtoolset-6-gcc-c++ предоставляет пользовательскую версию GCC, которая использует специальный скрипт компоновщика вместо динамической библиотеки для libstdc++.so. Это означает, что создаваемые им двоичные файлы не зависят от более новой версии libstdc++.so.6 и могут быть запущены на других компьютерах с CentOS, на которых не установлен devtoolset (т. е. на них установлена ​​только более старая библиотека libstdc++ из GCC 4.8).

Действительна ли эта конфигурация среды сборки?

Да. То, что вы видите, совершенно нормально, и так оно и должно работать.

Фрагменты более новой среды выполнения C++ из GCC 6.4.0 статически связываются с вашим двоичным файлом, и во время выполнения он зависит только от старого libstdc++.so, который установлен в каждой системе CentOS.

В этом весь смысл версии GCC для devtoolset.

atari83
30 декабря 2021 в 21:26
0

Виталий и Джонатан, спасибо вам обоим! Многое узнал из вопроса и ответа.