Ошибка «неопределенная ссылка» из статической библиотеки внешнего проекта паркета - PullRequest
0 голосов
/ 14 января 2019

Я хочу связать экспериментальный проект 'parquet' (https://github.com/apache/arrow/tree/master/cpp) как часть моего текущего проекта на Linux.

Для этого я запустил паркет с такими параметрами

cd build_parquet
cmake -DCMAKE_BUILD_TYPE=Release -DARROW_PARQUET=ON  \
 -DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_ROOT=${BOOST_BUILD_DIR}/include  -DBOOST_LIBRARYDIR=${BOOST_BUILD_DIR}/lib/boost -DARROW_BOOST_USE_SHARED=OFF -DBOOST_INCLUDEDIR=${BOOST_BUILD_DIR}/include/boost ..

cmake --build . --config Release

// Существует множество зависимостей, кроме boost, но для установки в системе требуется только boost, поскольку другие могут быть загружены и установлены скриптом cmake

Проект успешно скомпилирован. Я получил исполняемый файл, который можно запустить, сгенерировал статические библиотеки libarrow.a, libparquet.a, общие библиотеки libarrow.so, libparquet.so

В моем основном проекте я хочу использовать такие библиотеки и использую такие команды в cmake, чтобы найти их

find_path(PARQUET_INCLUDE_DIR NAMES arrow/api.h PATHS ${PARQUET_DIR}/src)

find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.a
              PATHS build_parquet/release/Release/ )

find_library(ARROW_LIBRARY_RELEASE NAMES arrow.a
             PATHS build_parquet/release/Release/ )

set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Parquet DEFAULT_MSG PARQUET_INCLUDE_DIR
                                  ${PARQUET_LIBRARIES_RELEASE } )

Это нормально, библиотеки и включения найдены.

Затем я связываю эти библиотеки с моим проектом

target_link_libraries(${myExe} ${PARQUET_LIBRARIES_RELEASE} ${mySomeOtherLibraries} )

после этого я получил огромное количество ошибок компоновщика, так что

libparquet.a(column_writer.cc.o): In function `apache::thrift::transport::TMemoryBuffer::~TMemoryBuffer()':
column_writer.cc:(.text._ZN6apache6thrift9transport13TMemoryBufferD0Ev[_ZN6apache6thrift9transport13TMemoryBufferD5Ev]+0x3): undefined reference to `vtable for apache::thrift::transport::TMemoryBuffer'
.....

вот что я не очень понимаю, почему lib хорошо скомпилирована в самом проекте паркетного компьютера, но сейчас у нее много нерешенных проблем, когда я использую ее для ссылок в своем собственном проекте? Более того, я скомпилировал проект для Windows, и когда я делал то же самое, но с arrow.lib и parquet.lib (вместо libparquet.a и libarrow.a) все работало нормально! Мне нужно было только положить arrow.dll, parquet.dll в исполняемые файлы для запуска проекта. Но в Linux у меня уже разбилась голова

Итак, почему это не работает, что я должен сделать, чтобы наконец связать проект с библиотекой?

Обновление

Я обнаружил проблему, мне пришлось связать библиотеки с добавлением .so файлов (не только .a файлов), как это


find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.so parquet.a
             PATHS build_parquet/release/Release/ )

find_library(ARROW_LIBRARY_RELEASE NAMES arrow.so arrow.a
            PATHS build_parquet/release/Release/ )

set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )

Проект построен. Итак, теперь возникает вопрос: зачем мне добавлять .so файлы в компоновщик (в Windows достаточно только статического .lib), всегда ли это происходит, когда я строю проект в Linux? Важен ли порядок связывания (сначала файлы .so, а затем файлы .a)

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Вы успешно собрали проект, когда связали с общими (.so) библиотеками вместо статических (.a).

(Команда find_library фактически ищет одну библиотеку , имя которой указано в опции NAMES. В вашем случае она нашла библиотеку .so, потому что ее имя предшествует .a).

На самом деле обе общие и статические parquet библиотеки содержат одинаковый набор символов , и оба набора недостаточно для ссылки. Разница в том, что shared library содержит информацию , где найти оставшиеся символы (в библиотеке thrift в вашем случае), а статическая библиотека - нет.

Для правильной связи с статическими библиотеками необходимо составить список зависимых библиотек вручную .


В Windows файл .lib может означать либо * статическая библиотека, либо файл импорта для shared (.dll). Похоже, вы связываетесь с динамическим (у него нет префикса lib ), который успешно работает, как в Linux.

0 голосов
/ 16 января 2019

Как написал Уве в комментарии, хранилище https://github.com/apache/parquet-cpp устарело, а библиотека Parquet C ++ разрабатывается как часть кодовой базы Apache Arrow C ++ https://github.com/apache/arrow/tree/master/cpp. Можете ли вы попробовать построить на основе этого и если у вас возникли проблемы, можете ли вы публиковать их в списке рассылки dev@arrow.apache.org?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...