Вопрос или проблема
Я пытаюсь скомпилировать простую программу с помощью clang++ с пользовательским libc++, который я собрал из исходного кода. Во время компиляции я получаю странную ошибку, которая, на мой взгляд, указывает на то, что clang связывается с libstdc++ в дополнение к libc++. Правильна ли эта оценка, и если да, то что я могу сделать, чтобы ее исправить?
libc-with-memsan — это мой собственный компилированный libc++.
Команда(ы) clang:
LIBCXX="/nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8"
MSAN_CFLAGS="-fsanitize=memory -stdlib=libc++ -L${LIBCXX}/lib -lc++abi -I${LIBCXX}/include -I${LIBCXX}/include/c++/v1"
clang++ ${MSAN_CFLAGS} src/main.cpp -o target/output -fsanitize=memory -fsanitize-memory-track-origins -Wl,--verbose,-rpath,${LIBCXX}/lib -v
Вывод:
clang version 18.1.8
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /nix/store/5h0y9g4vmz9189zbzawhy3rxwgwqa5xw-clang-18.1.8/bin
Found candidate GCC installation: /nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/lib/gcc/x86_64-unknown-linux-gnu/13.2.0
Found candidate GCC installation: /nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/lib64/gcc/x86_64-unknown-linux-gnu/13.2.0
Selected GCC installation: /nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/lib64/gcc/x86_64-unknown-linux-gnu/13.2.0
Candidate multilib: .;@m64
Selected multilib: .;@m64
"/nix/store/5h0y9g4vmz9189zbzawhy3rxwgwqa5xw-clang-18.1.8/bin/clang++" -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -dumpdir target/output- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/tim/Documents/mpi_test -v -fcoverage-compilation-dir=/home/tim/Documents/mpi_test -nostdsysteminc -resource-dir /nix/store/n0gsdqcq4hjkc92qdpyb2aw9lihrpbfs-clang-wrapper-18.1.8/resource-root -idirafter /nix/store/0ywz89gl18p0y5m7m8kz8vh1bkry0syf-glibc-2.39-52-dev/include -isystem /nix/store/g1f6lp35qm498n6fa0g6a6qic1rqra6s-openmpi-with-memsan-4.1.6-dev/include -isystem /nix/store/z03vnq1lvv0xz98rdbssa8mg77dv47ns-openmpi-4.1.6-dev/include -isystem /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include -isystem /nix/store/frs3xih2qnnz97rsw6ba202h9vmn31w3-compiler-rt-libc-18.1.8-dev/include -isystem /nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0 -isystem /nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0/x86_64-unknown-linux-gnu -I /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include -I /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1 -internal-isystem /nix/store/n0gsdqcq4hjkc92qdpyb2aw9lihrpbfs-clang-wrapper-18.1.8/resource-root/include -source-date-epoch 315532800 -fdeprecated-macro -ferror-limit 19 -fsanitize=memory -fsanitize-system-ignorelist=/nix/store/n0gsdqcq4hjkc92qdpyb2aw9lihrpbfs-clang-wrapper-18.1.8/resource-root/share/msan_ignorelist.txt -fsanitize-memory-track-origins=2 -fsanitize-memory-use-after-dtor -fno-sanitize-address-use-odr-indicator -fno-assume-sane-operator-new -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /run/user/1000/main-8ebcbb.o -x c++ src/main.cpp
clang -cc1 version 18.1.8 based upon LLVM 18.1.8 default target x86_64-unknown-linux-gnu
ignoring duplicate directory "/nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include"
as it is a non-system directory that duplicates a system directory
#include "..." search starts here:
#include <...> search starts here:
/nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1
/nix/store/g1f6lp35qm498n6fa0g6a6qic1rqra6s-openmpi-with-memsan-4.1.6-dev/include
/nix/store/z03vnq1lvv0xz98rdbssa8mg77dv47ns-openmpi-4.1.6-dev/include
/nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include
/nix/store/frs3xih2qnnz97rsw6ba202h9vmn31w3-compiler-rt-libc-18.1.8-dev/include
/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0
/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0/x86_64-unknown-linux-gnu
/nix/store/n0gsdqcq4hjkc92qdpyb2aw9lihrpbfs-clang-wrapper-18.1.8/resource-root/include
/nix/store/0ywz89gl18p0y5m7m8kz8vh1bkry0syf-glibc-2.39-52-dev/include
End of search list.
In file included from src/main.cpp:2:
In file included from /nix/store/g1f6lp35qm498n6fa0g6a6qic1rqra6s-openmpi-with-memsan-4.1.6-dev/include/mpi.h:2911:
In file included from /nix/store/g1f6lp35qm498n6fa0g6a6qic1rqra6s-openmpi-with-memsan-4.1.6-dev/include/openmpi/ompi/mpi/cxx/mpicxx.h:42:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/map:574:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/__algorithm/equal.h:20:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/__string/constexpr_c_functions.h:14:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/__memory/construct_at.h:23:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/new:364:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/cstdlib:87:
In file included from /nix/store/1al3szdgkdqsz7r7fcndvrvsc8vx215b-libc-with-memsan-18.1.8/include/c++/v1/stdlib.h:94:
/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0/stdlib.h:38:12: error: no member named 'abort' in namespace 'std'
38 | using std::abort;
| ~~~~~^
/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0/stdlib.h:39:12: error: no member named 'atexit' in namespace 'std'
39 | using std::atexit;
| ~~~~~^
/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0/stdlib.h:40:12: error: no member named 'exit' in namespace 'std'
40 | using std::exit;
| ~~~~~^
Как видите, цепочка импорта выглядит следующим образом:
main.cpp -> openmpi -> libc++ -> libc++ -> … -> libc++ -> gcc ?!?!?!
PS:
- Игнорируйте странные пути, это всего лишь проделки NixOS.
- Как видно из импортов, я использую OpenMPI. Ошибка остается такой же при использовании mpicxx с бэкендом clang++, так что это тоже не является проблемой.
Ответ или решение
Ошибка, с которой вы столкнулись, указывает на то, что ваш код в процессе компиляции ссылается на библиотеку libstdc++, в то время как вы ожидаете использования libc++. Давайте подробно разберемся с этой проблемой и подойдем к ее решению.
1. Понимание проблемы
Вы используете clang++
с явно указанными флагами для подключения libc++. Однако, анализируя вывод компиляции, можно заметить, что компилятор пытается включить файлы заголовков из libstdc++ (/nix/store/1hn524ifk2hqksf0m9klmh9gkfkfvgqv-gcc-13.2.0/include/c++/13.2.0
). Это происходит из-за того, что OpenMPI может использовать libstdc++ и требуется C++ функциональность, которую он реализует.
Ваша программа, импортируя заголовочные файлы OpenMPI, вызывает каскадное включение заголовков, которые в конечном итоге приводят к конфликту между библиотеками и отсутствию необходимых функций управления выходом, таких как std::abort
, std::atexit
, и std::exit
.
2. Позвонок причины
Имеются несколько возможных причин этой проблемы:
-
Конфликт библиотек: Установленные библиотечные зависимости могут перетаскивать неподходящие заголовочные файлы в вашу компиляцию. Это может произойти, если на вашей машине существуют установленные версии как libstdc++, так и libc++, и OpenMPI ссылается на libstdc++.
-
Неправильные флаги компиляции: Если флаги компиляции неявно указывают на использование стандартной библиотеки GCC, несмотря на использование libc++, это будет способствовать трудноразрешимым проблемам.
3. Решения
Следуйте предложенным шагам ниже для устранения проблемы:
Шаг 1: Убедитесь в чистоте среды
Проверьте, что у вас нет конфликтующих версий библиотек. Вы можете использовать консольные команды, чтобы искать все версии установленных библиотек:
ls /usr/lib/x86_64-linux-gnu/libstdc++.so*
ls /usr/lib/x86_64-linux-gnu/libc++.so*
Удалите или переименуйте библиотеки старых версий, если они присутствуют.
Шаг 2: Используйте флаги компиляции правильно
Убедитесь, что ваши флаги компиляции настроены корректно. Попробуйте добавить флаг -nostdlib++
в ваши MSAN_CFLAGS
, что даст команду компилятору полностью игнорировать системные заголовочные файлы из libstdc++:
MSAN_CFLAGS="-fsanitize=memory -stdlib=libc++ -L${LIBCXX}/lib -lc++abi -I${LIBCXX}/include -I${LIBCXX}/include/c++/v1 -nostdlib++"
Шаг 3: Уточнение и изоляция зависимостей
Поскольку ваш проект использует OpenMPI, рекомендуется убедиться в том, что оно совместимо с C++ стандартной библиотекой, которую вы используете. Возможно, вам потребуется установить версию OpenMPI, скомпилированную для работы с libc++, чтобы предотвратить подобные конфликты.
Шаг 4: Оптимизация окружения Nix
Если вы используете NixOS, можете рассмотреть использование nix-shell
для создания чистого окружения, в котором вы можете точно указывать, какие зависимости использовать. Таким образом, возможно, получится создать среду, где только libc++ доступен без воздействия libstdc++.
Заключение
Если вы выполните все предложенные шаги и учтете приведенные рекомендации, это должно устранить вашу проблему во время компиляции. Проблема, с которой вы столкнулись, типична при смешивании нескольких стандартных библиотек в одном проекте, и внимательное планирование и установка корректных флагов компиляции способны помочь в ее решении.