#cmake #shared-libraries #undefined-symbol #c-standard-library #sundials
#cmake #разделяемые библиотеки #неопределенный символ #c-standard-library #солнечные часы
Вопрос:
Моей целью было создать разделяемые библиотеки из SUNDIALS 2.7.0 — это решатели обыкновенных дифференциальных уравнений, написанные на C.
Я загрузил исходный код и следовал руководству по установке:
- запустите Cmake (с графическим интерфейсом), проверил параметры «CVODE» (это один из доступных решателей — единственный, который я хотел), «создавать разделяемые библиотеки» и «использовать общие (std-c) математические библиотеки» и сгенерировал Makefile.
- запуск
make amp;amp; make install
в консоли Linux, и мои разделяемые библиотеки были сгенерированы без сообщений об ошибках вообще. Вот результат:
$ make
Scanning dependencies of target sundials_nvecserial_shared
[ 3%] Building C object src/nvec_ser/CMakeFiles/sundials_nvecserial_shared.dir/nvector_serial.c.o
[ 7%] Building C object src/nvec_ser/CMakeFiles/sundials_nvecserial_shared.dir/__/sundials/sundials_math.c.o
[ 11%] Linking C shared library libsundials_nvecserial.so
[ 11%] Built target sundials_nvecserial_shared
Scanning dependencies of target sundials_cvode_shared
[ 14%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode.c.o
[ 18%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_io.c.o
[ 22%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_direct.c.o
[ 25%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_band.c.o
[ 29%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_dense.c.o
[ 33%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_diag.c.o
[ 37%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spils.c.o
[ 40%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spbcgs.c.o
[ 44%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spgmr.c.o
[ 48%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_sptfqmr.c.o
[ 51%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_sparse.c.o
[ 55%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_bandpre.c.o
[ 59%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_bbdpre.c.o
[ 62%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_nvector.c.o
[ 66%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_math.c.o
[ 70%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_direct.c.o
[ 74%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_band.c.o
[ 77%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_dense.c.o
[ 81%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_iterative.c.o
[ 85%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_sparse.c.o
[ 88%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_spbcgs.c.o
[ 92%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_spgmr.c.o
[ 96%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_sptfqmr.c.o
[100%] Linking C shared library libsundials_cvode.so
[100%] Built target sundials_cvode_shared
$ sudo make install
[ 11%] Built target sundials_nvecserial_shared
[100%] Built target sundials_cvode_shared
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/sundials/sundials_config.h
Install shared components
-- Installing: /usr/local/include/sundials/sundials_band.h
-- Installing: /usr/local/include/sundials/sundials_dense.h
-- Installing: /usr/local/include/sundials/sundials_direct.h
-- Installing: /usr/local/include/sundials/sundials_iterative.h
-- Installing: /usr/local/include/sundials/sundials_math.h
-- Installing: /usr/local/include/sundials/sundials_nvector.h
-- Installing: /usr/local/include/sundials/sundials_fnvector.h
-- Installing: /usr/local/include/sundials/sundials_pcg.h
-- Installing: /usr/local/include/sundials/sundials_sparse.h
-- Installing: /usr/local/include/sundials/sundials_spbcgs.h
-- Installing: /usr/local/include/sundials/sundials_spfgmr.h
-- Installing: /usr/local/include/sundials/sundials_spgmr.h
-- Installing: /usr/local/include/sundials/sundials_sptfqmr.h
-- Installing: /usr/local/include/sundials/sundials_types.h
Install NVECTOR_SERIAL
-- Installing: /usr/local/lib/libsundials_nvecserial.so.2.7.0
-- Installing: /usr/local/lib/libsundials_nvecserial.so.2
-- Installing: /usr/local/lib/libsundials_nvecserial.so
-- Installing: /usr/local/include/nvector/nvector_serial.h
Install CVODE
-- Installing: /usr/local/lib/libsundials_cvode.so.2.9.0
-- Installing: /usr/local/lib/libsundials_cvode.so.2
-- Installing: /usr/local/lib/libsundials_cvode.so
-- Installing: /usr/local/include/cvode/cvode_band.h
-- Installing: /usr/local/include/cvode/cvode_bandpre.h
-- Installing: /usr/local/include/cvode/cvode_bbdpre.h
-- Installing: /usr/local/include/cvode/cvode_dense.h
-- Installing: /usr/local/include/cvode/cvode_diag.h
-- Installing: /usr/local/include/cvode/cvode_direct.h
-- Installing: /usr/local/include/cvode/cvode.h
-- Installing: /usr/local/include/cvode/cvode_sparse.h
-- Installing: /usr/local/include/cvode/cvode_spbcgs.h
-- Installing: /usr/local/include/cvode/cvode_spgmr.h
-- Installing: /usr/local/include/cvode/cvode_spils.h
-- Installing: /usr/local/include/cvode/cvode_sptfqmr.h
-- Installing: /usr/local/include/cvode/cvode_impl.h
Эти разделяемые библиотеки, похоже, функционируют должным образом в моем проекте, для чего они мне и были нужны — обыкновенные дифференциальные уравнения решаются, и результат, похоже, идентичен другим решателям, которые не зависят от них.
Но есть одно большое но 🙂: проверка на наличие неопределенных символов в сгенерированных разделяемых библиотеках покажите мне краткий список стандартных функций — вот выходные данные для разделяемых библиотек:
$ nm -D --undefined-only libsundials_cvode.so.2.9.0
w __cxa_finalize
U exp
U fprintf
U fputc
U free
U fwrite
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U malloc
U memset
U pow
U printf
U putchar
U realloc
U sqrt
U __stack_chk_fail
U stderr
U vsprintf
и
$ nm -D --undefined-only libsundials_nvecserial.so.2.7.0
w __cxa_finalize
U exp
U free
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U malloc
U pow
U printf
U putchar
U sqrt
Печать зависимостей разделяемой библиотеки дает:
$ ldd -r libsundials_nvecserial.so
linux-vdso.so.1 (0x00007ffd657a5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fecd8155000)
/lib64/ld-linux-x86-64.so.2 (0x00007fecd874c000)
undefined symbol: exp (./libsundials_nvecserial.so)
undefined symbol: pow (./libsundials_nvecserial.so)
undefined symbol: sqrt (./libsundials_nvecserial.so)
и
$ ldd -r libsundials_cvode.so linux-vdso.so.1 (0x00007ffe6a1ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6cd55ac000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6cd5bc8000)
undefined symbol: exp (./libsundials_cvode.so)
undefined symbol: pow (./libsundials_cvode.so)
undefined symbol: sqrt (./libsundials_cvode.so)
Существуют, например, такие функции, как SUNRsqrt, которые определяются через sqrt и очень важны в реальных численных вычислениях — этот факт, а также наличие неопределенных символов, приводит меня в замешательство и беспокоит надежность разделяемых библиотек.
Перед созданием разделяемых библиотек я установил все соответствующие пути к переменной среды LD_LIBRARY_PATH (которая, кстати, раньше была пустой):
$ export LD_LIBRARY_PATH="/usr/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu"
$ echo $LD_LIBRARY_PATH
/usr/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu
Например, стандартная библиотека C libc.so и математическая библиотека C libm.so хранятся в /usr/lib/x86_64-linux-gnu, тогда как библиотека транзакционной памяти GNU libitim.so хранится в /usr/lib/gcc/x86_64-linux-gnu (хотя версия1.0.0 этого также находится в /usr/lib/x86_64-linux-gnu).
Версии OS, Cmake, компилятора GNU C и GNU создают:
$ lsb_release -d
Description: Ubuntu 18.04.5 LTS
$ cmake --version
cmake version 3.18.2
$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$ make --version
GNU Make 4.1
Любые комментарии будут с благодарностью.
PS Этот случай полностью воспроизводим, поскольку речь идет о создании разделяемых библиотек из исходного кода SUNDIALS 2.7.0 (прямая ссылка для скачивания) и проверке их на неопределенные символы.
Ответ №1:
У вас есть неопределенный символ с ldd, потому что файлы so были созданы без -lm
опции. Однако это не будет проблемой, если конечный исполняемый файл связан с -lm
опцией. Это то, что делается для тестов, подобных test_nvector_serial
который связан с -lm -lrt
.
Вы можете увидеть все это, запустив make в подробном режиме с make VERBOSE=1
. Если вы попытаетесь сгенерировать исполняемый файл без -lm
вас collect2: error: ld returned 1 exit status
и компоновщика, жалующихся на exp, pow и sqrt. если вы добавите -lm
при создании файлов so (я это сделал). вы увидите :
ldd -r ./src/nvec_ser/libsundials_nvecserial.so
linux-vdso.so.1 (0x00007ffe1a769000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe4a5c19000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe4a5828000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe4a61bd000)
И в этом случае вы можете связать свои тесты (только для того, чтобы выполнить некоторый тест для себя, если хотите) без -lm
.
Для компиляции ваших файлов so с -lm
. Вы можете сделать это, запустив командную строку с -lm
опцией после ввода нужной папки (только для целей тестирования). Другой способ заключается в изменении CMakeLists.txt которые генерируют файлы so. libsundials_nvecserial.so
Например, вы изменяете, sundials-2.7.0/src/nvec_ser/CMakeLists.txt
добавляя target_link_libraries(sundials_nvecserial_shared -lm)
после ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES})
.
Для LD_LIBRARY_PATH он не обязательно должен содержать что-то обязательно, если вы смотрите в стандартных местах. Компоновщик также использует /etc /ld.so.cache и выполняет поиск также по пути по умолчанию, если вы не используете — z nodeflib
. вы можете найти более подробную информацию вhttps://man7.org/linux/man-pages/man8/ld.so.8.html
Для nm -D. Это нормально, попробуйте скомпилировать hello world gcc -o exec hello.c
вы увидите, что printf не определен. Взгляните на динамическое связывание, а также на -rdynamic
параметр, используемый для создания файлов so.
Комментарии:
1. Не могли бы вы рассказать мне, как добавить «‘-lm»‘ при создании файлов .so? Я попытался добавить CMAKE_C_FLAGS=-lm или CMAKE_SHARED_LINK-FLAGS=-lm (используя CMake GUI), но это приводит к добавлению «‘-lm»‘ до, а не после исходных файлов / .so (я заметил это в подробном отчете о создании, как вы предложили). И поможет ли это с другими неопределенными символами, которые были найдены с помощью утилиты «‘nm -D — undefined-only»‘?
2. Я попытался отредактировать CMakeFile.txt также, используя
add_library()
иtarget_link_directories()
, но так и не удалось избавиться от неопределенных символов @yflelion3. предоставленные вами сведения решили проблему с неопределенными символами в выходных
ldd
данных утилиты. Да благословит вас Бог, @yflelion