неопределенные символы остаются, но общие библиотеки компилируются и, похоже, работают правильно

Моей целью было построить разделяемые библиотеки из SUNDIALS 2.7.0 - это решатели обыкновенных дифференциальных уравнений, написанных на C.

Я загрузил исходный код и выполнил руководство по установке:

  1. запустите Cmake (с графическим интерфейсом), отметьте опции "CVODE" (это один из доступных решателей - единственный, который я хотел), "создать общие библиотеки" и "использовать общие (std-c) математические библиотеки" и сгенерировал Makefile.
  2. бежать make && 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).

Версии ОС, Cmake, компилятора GNU C и GNU Make:

$ 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. Это нормально, попробуй скомпилировать привет мир gcc -o exec hello.cвы увидите, что printf не определен. Взгляните на динамическое связывание, а также на -rdynamic опция, используемая для создания файлов so.

Другие вопросы по тегам